diff --git a/LICENSES/elfio.txt b/LICENSES/elfio.txt deleted file mode 100644 index 0f25e4bae..000000000 --- a/LICENSES/elfio.txt +++ /dev/null @@ -1,19 +0,0 @@ -ELFIO.h - ELF reader and producer. -Copyright (C) 2001 Serge Lamikhov-Center - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -The GNU Library GPL is available at http://www.gnu.org/copyleft/lesser.html - diff --git a/LICENSES/fontconfig.txt b/LICENSES/fontconfig.txt deleted file mode 100644 index eb766faed..000000000 --- a/LICENSES/fontconfig.txt +++ /dev/null @@ -1,23 +0,0 @@ -http://www.jclark.com/xml/copying.txt - -Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/LICENSES/libxml.txt b/LICENSES/libxml.txt deleted file mode 100644 index a5c4e6689..000000000 --- a/LICENSES/libxml.txt +++ /dev/null @@ -1,29 +0,0 @@ -http://xmlsoft.org/ -http://www.opensource.org/licenses/mit-license.html - -Open Source Initiative OSI - The MIT License:Licensing -Tue, 2006-10-31 04:56 . nelson - -The MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - diff --git a/LICENSES/openal.txt b/LICENSES/openal.txt deleted file mode 100644 index d0c897869..000000000 --- a/LICENSES/openal.txt +++ /dev/null @@ -1,484 +0,0 @@ - - GNU LIBRARY GENERAL PUBLIC LICENSE - Version 2, June 1991 - - - Copyright (C) 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the library GPL. It is - numbered 2 because it goes with version 2 of the ordinary GPL.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Library General Public License, applies to some -specially designated Free Software Foundation software, and to any -other libraries whose authors decide to use it. You can use it for -your libraries, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if -you distribute copies of the library, or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link a program with the library, you must provide -complete object files to the recipients so that they can relink them -with the library, after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - Our method of protecting your rights has two steps: (1) copyright -the library, and (2) offer you this license which gives you legal -permission to copy, distribute and/or modify the library. - - Also, for each distributor's protection, we want to make certain -that everyone understands that there is no warranty for this free -library. If the library is modified by someone else and passed on, we -want its recipients to know that what they have is not the original -version, so that any problems introduced by others will not reflect on -the original authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that companies distributing free -software will individually obtain patent licenses, thus in effect -transforming the program into proprietary software. To prevent this, -we have made it clear that any patent must be licensed for everyone's -free use or not licensed at all. - - Most GNU software, including some libraries, is covered by the ordinary -GNU General Public License, which was designed for utility programs. This -license, the GNU Library General Public License, applies to certain -designated libraries. This license is quite different from the ordinary -one; be sure to read it in full, and don't assume that anything in it is -the same as in the ordinary license. - - The reason we have a separate public license for some libraries is that -they blur the distinction we usually make between modifying or adding to a -program and simply using it. Linking a program with a library, without -changing the library, is in some sense simply using the library, and is -analogous to running a utility program or application program. However, in -a textual and legal sense, the linked executable is a combined work, a -derivative of the original library, and the ordinary General Public License -treats it as such. - - Because of this blurred distinction, using the ordinary General -Public License for libraries did not effectively promote software -sharing, because most developers did not use the libraries. We -concluded that weaker conditions might promote sharing better. - - However, unrestricted linking of non-free programs would deprive the -users of those programs of all benefit from the free status of the -libraries themselves. This Library General Public License is intended to -permit developers of non-free programs to use free libraries, while -preserving your freedom as a user of such programs to change the free -libraries that are incorporated in them. (We have not seen how to achieve -this as regards changes in header files, but we have achieved it as regards -changes in the actual functions of the Library.) The hope is that this -will lead to faster development of free libraries. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, while the latter only -works together with the library. - - Note that it is possible for a library to be covered by the ordinary -General Public License rather than by this special one. - - GNU LIBRARY GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library which -contains a notice placed by the copyright holder or other authorized -party saying it may be distributed under the terms of this Library -General Public License (also called "this License"). Each licensee is -addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also compile or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - c) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - d) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the source code distributed need not include anything that is normally -distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Library General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - diff --git a/LICENSES/qt-4.5-linden-changes.txt b/LICENSES/qt-4.5-linden-changes.txt deleted file mode 100644 index d424824cb..000000000 --- a/LICENSES/qt-4.5-linden-changes.txt +++ /dev/null @@ -1,5 +0,0 @@ -The pristine version of Qt corresponding to this build is available at: -http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/qt-all-opensource-src-4.5.2.tar.bz2 - -The patches we applied to the above package to get this build are available at: -http://hg.secondlife.com/llqtwebkit/src/tip/qt_patches/ diff --git a/etc/message.xml b/etc/message.xml index 690103bb7..330ecee48 100644 --- a/etc/message.xml +++ b/etc/message.xml @@ -378,14 +378,7 @@ true - ParcelMediaURLFilter - - flavor - llsd - trusted-sender - false - - + ParcelNavigateMedia flavor @@ -572,6 +565,14 @@ false + ObjectPhysicsProperties + + flavor + llsd + trusted-sender + true + + DisplayNameUpdate diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 09eade34f..e81965cc6 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -30,11 +30,11 @@ include(BuildVersion) include(UnixInstall) -set (GCC_DISABLE_FATAL_WARNINGS TRUE) +set (DISABLE_FATAL_WARNINGS TRUE) if (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE ReleaseSSE2 CACHE STRING - "Build type. One of: Debug Release ReleaseSSE2 RelWithDebInfo" FORCE) + set(CMAKE_BUILD_TYPE Release CACHE STRING + "Build type. One of: Debug Release RelWithDebInfo" FORCE) endif (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) # Create a 'prepare' target in which to perform setup actions. This @@ -77,6 +77,7 @@ if (VIEWER) add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger) add_subdirectory(${LIBS_OPEN_PREFIX}llplugin) add_subdirectory(${LIBS_OPEN_PREFIX}llui) + add_subdirectory(${LIBS_OPEN_PREFIX}llxuixml) # viewer plugins directory add_subdirectory(${LIBS_OPEN_PREFIX}plugins) diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 7ce670a36..d7a2ec8c9 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -12,17 +12,12 @@ set(CMAKE_CXX_FLAGS_RELEASE "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=1 -DNDEBUG") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") -set(CMAKE_CXX_FLAGS_RELEASESSE2 - "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=1 -DNDEBUG") -#llimage now requires this (?) -set(CMAKE_C_FLAGS_RELEASESSE2 - "${CMAKE_CXX_FLAGS_RELEASESSE2}") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DLL_RELEASE=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1") # Don't bother with a MinSizeRel build. -set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;ReleaseSSE2;Debug" CACHE STRING +set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;Debug" CACHE STRING "Supported build types." FORCE) # Platform-specific compilation flags. @@ -40,23 +35,17 @@ if (WINDOWS) "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP /arch:SSE2" CACHE STRING "C++ compiler release-with-debug options" FORCE) set(CMAKE_CXX_FLAGS_RELEASE - "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP /arch:SSE /fp:fast" + "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP /arch:SSE2 /fp:fast" CACHE STRING "C++ compiler release options" FORCE) set(CMAKE_C_FLAGS_RELEASE - "${CMAKE_C_FLAGS_RELEASE} ${LL_C_FLAGS} /O2 /Zi /MD /MP /arch:SSE /fp:fast" + "${CMAKE_C_FLAGS_RELEASE} ${LL_C_FLAGS} /O2 /Zi /MD /MP /arch:SSE2 /fp:fast" CACHE STRING "C compiler release options" FORCE) - set(CMAKE_CXX_FLAGS_RELEASESSE2 - "${CMAKE_CXX_FLAGS_RELEASESSE2} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP /arch:SSE2 /fp:fast" - CACHE STRING "C++ compiler release-SSE2 options" FORCE) - set(CMAKE_C_FLAGS_RELEASESSE2 - "${CMAKE_C_FLAGS_RELEASESSE2} ${LL_C_FLAGS} /O2 /Zi /MD /MP /arch:SSE2 /fp:fast" - CACHE STRING "C compiler release-SSE2 options" FORCE) set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LARGEADDRESSAWARE") set(CMAKE_CXX_STANDARD_LIBRARIES "") set(CMAKE_C_STANDARD_LIBRARIES "") - + add_definitions( /DLL_WINDOWS=1 /DUNICODE @@ -78,38 +67,35 @@ if (WINDOWS) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0" CACHE STRING "C++ compiler release options" FORCE) - set(CMAKE_CXX_FLAGS_RELEASESSE2 - "${CMAKE_CXX_FLAGS_RELEASESSE2} -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0" - CACHE STRING "C++ compiler release-SSE2 options" FORCE) - set(CMAKE_C_FLAGS_RELEASESSE2 - "${CMAKE_CXX_FLAGS_RELEASESSE2} -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0" - CACHE STRING "C compiler release-SSE2 options" FORCE) + set(CMAKE_C_FLAGS_RELEASE + "${CMAKE_CXX_FLAGS_RELEASE} -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0" + CACHE STRING "C compiler release options" FORCE) add_definitions( /Zc:wchar_t- ) endif (MSVC80 OR MSVC90 OR MSVC10) # Are we using the crummy Visual Studio KDU build workaround? - if (NOT VS_DISABLE_FATAL_WARNINGS) + if (NOT DISABLE_FATAL_WARNINGS) add_definitions(/WX) - endif (NOT VS_DISABLE_FATAL_WARNINGS) + endif (NOT DISABLE_FATAL_WARNINGS) # Various libs are compiler specific, generate some variables here we can just use # when we require them instead of reimplementing the test each time. if (MSVC71) - set(MSVC_DIR 7.1) - set(MSVC_SUFFIX 71) - elseif (MSVC80) - set(MSVC_DIR 8.0) - set(MSVC_SUFFIX 80) - elseif (MSVC90) - set(MSVC_DIR 9.0) - set(MSVC_SUFFIX 90) - elseif (MSVC10) - set(MSVC_DIR 10.0) - set(MSVC_SUFFIX 100) - endif (MSVC71) + set(MSVC_DIR 7.1) + set(MSVC_SUFFIX 71) + elseif (MSVC80) + set(MSVC_DIR 8.0) + set(MSVC_SUFFIX 80) + elseif (MSVC90) + set(MSVC_DIR 9.0) + set(MSVC_SUFFIX 90) + elseif (MSVC10) + set(MSVC_DIR 10.0) + set(MSVC_SUFFIX 100) + endif (MSVC71) if (MSVC10) SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO") @@ -125,103 +111,157 @@ set (GCC_EXTRA_OPTIMIZATIONS "-ffast-math") if (LINUX) set(CMAKE_SKIP_RPATH TRUE) - # Here's a giant hack for Fedora 8, where we can't use - # _FORTIFY_SOURCE if we're using a compiler older than gcc 4.1. - - find_program(GXX g++) - mark_as_advanced(GXX) - - if (GXX) - execute_process( - COMMAND ${GXX} --version - COMMAND sed "s/^[gc+ ]*//" - COMMAND head -1 - OUTPUT_VARIABLE GXX_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - else (GXX) - set(GXX_VERSION x) - endif (GXX) - - # The quoting hack here is necessary in case we're using distcc or - # ccache as our compiler. CMake doesn't pass the command line - # through the shell by default, so we end up trying to run "distcc" - # " g++" - notice the leading space. Ugh. - - execute_process( - COMMAND sh -c "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} --version" - COMMAND sed "s/^[gc+ ]*//" - COMMAND head -1 - OUTPUT_VARIABLE CXX_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) - - if (${GXX_VERSION} STREQUAL ${CXX_VERSION}) - add_definitions(-D_FORTIFY_SOURCE=2) - else (${GXX_VERSION} STREQUAL ${CXX_VERSION}) - if (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat") - add_definitions(-D_FORTIFY_SOURCE=2) - endif (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat") - endif (${GXX_VERSION} STREQUAL ${CXX_VERSION}) - - #Lets actually get a numerical version of gxx's version - STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION ${CXX_VERSION}) - - #gcc 4.3 and above don't like the LL boost - if(${CXX_VERSION} GREATER 429) - add_definitions(-Wno-parentheses) - endif (${CXX_VERSION} GREATER 429) - - #gcc 4.6 has a new spammy warning - if(NOT ${CXX_VERSION} LESS 460) - add_definitions(-Wno-unused-but-set-variable) - endif (NOT ${CXX_VERSION} LESS 460) - - # End of hacks. - add_definitions( -DLL_LINUX=1 + -DAPPID=secondlife -D_REENTRANT -fexceptions -fno-math-errno -fno-strict-aliasing -fsigned-char + -fvisibility=hidden -g -pthread ) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") + # Don't catch SIGCHLD in our base application class for the viewer + # some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! + # The viewer doesn't need to catch SIGCHLD anyway. + add_definitions(-DLL_IGNORE_SIGCHLD) + + if(${CMAKE_C_COMPILER} MATCHES "gcc*") + find_program(GXX g++) + mark_as_advanced(GXX) + + if (GXX) + execute_process( + COMMAND ${GXX} --version + COMMAND sed "s/^[gc+ ]*//" + COMMAND head -1 + OUTPUT_VARIABLE GXX_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + else (GXX) + set(GXX_VERSION x) + endif (GXX) + + # The quoting hack here is necessary in case we're using distcc or + # ccache as our compiler. CMake doesn't pass the command line + # through the shell by default, so we end up trying to run "distcc" + # " g++" - notice the leading space. Ugh. + + execute_process( + COMMAND sh -c "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} --version" + COMMAND sed "s/^[gc+ ]*//" + COMMAND head -1 + OUTPUT_VARIABLE CXX_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + + # Here's a giant hack for Fedora 8, where we can't use + # _FORTIFY_SOURCE if we're using a compiler older than gcc 4.1. + if (${GXX_VERSION} STREQUAL ${CXX_VERSION}) + add_definitions(-D_FORTIFY_SOURCE=2) + else (${GXX_VERSION} STREQUAL ${CXX_VERSION}) + if (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat") + add_definitions(-D_FORTIFY_SOURCE=2) + endif (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat") + endif (${GXX_VERSION} STREQUAL ${CXX_VERSION}) + + #Lets actually get a numerical version of gxx's version + STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION ${CXX_VERSION}) + + #gcc 4.3 and above doesn't like the LL boost + if(${CXX_VERSION} GREATER 429) + add_definitions(-Wno-parentheses) + endif (${CXX_VERSION} GREATER 429) + + #gcc 4.6 has a new spammy warning + if(NOT ${CXX_VERSION} LESS 460) + add_definitions(-Wno-unused-but-set-variable) + endif (NOT ${CXX_VERSION} LESS 460) + + # End of hacks. + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") - add_definitions(-DAPPID=secondlife) - add_definitions(-fvisibility=hidden) - # don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway. - add_definitions(-DLL_IGNORE_SIGCHLD) - if (NOT STANDALONE) - # this stops us requiring a really recent glibc at runtime - add_definitions(-fno-stack-protector) - endif (NOT STANDALONE) - if (${ARCH} STREQUAL "x86_64") - add_definitions(-DLINUX64=1 -pipe) - set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") - set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") - else (${ARCH} STREQUAL "x86_64") if (NOT STANDALONE) - set(MARCH_FLAG " -march=pentium4") + # this stops us requiring a really recent glibc at runtime + add_definitions(-fno-stack-protector) endif (NOT STANDALONE) - set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - endif (${ARCH} STREQUAL "x86_64") + if (${ARCH} STREQUAL "x86_64") + add_definitions(-DLINUX64=1 -pipe) + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") + else (${ARCH} STREQUAL "x86_64") + if (NOT STANDALONE) + set(MARCH_FLAG " -march=pentium4") + endif (NOT STANDALONE) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + endif (${ARCH} STREQUAL "x86_64") + elseif(${CMAKE_C_COMPILER} MATCHES "clang*") + find_program(CLANG clang) + mark_as_advanced(CLANG) + + find_program(CLANGXX clang++) + mark_as_advanced(CLANGXX) - set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG} -msse2") + add_definitions( + -D_FORTIFY_SOURCE=2 + ) + + if (NOT STANDALONE) + # this stops us requiring a really recent glibc at runtime + add_definitions(-fno-stack-protector) + endif (NOT STANDALONE) + + if (NOT STANDALONE) + set(MARCH_FLAG " -march=pentium4") + endif (NOT STANDALONE) + + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}${MARCH_FLAG} -msse2") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}${MARCH_FLAG} -msse2") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -msse2") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -msse2") + elseif(${CMAKE_C_COMPILER} MATCHES "icc*" AND ${CMAKE_CXX_COMPILER} MATCHES "icpc*") + find_program(ICC icc) + mark_as_advanced(ICC) + + add_definitions( + -D_FORTIFY_SOURCE=2 + ) + + if (NOT STANDALONE) + # this stops us requiring a really recent glibc at runtime + add_definitions(-fno-stack-protector) + endif (NOT STANDALONE) + + if (NOT STANDALONE) + set(MARCH_FLAG " -axsse4.1 -msse2") + endif (NOT STANDALONE) + + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline-functions") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline-functions") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}${MARCH_FLAG} -parallel -fp-model fast=1") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}${MARCH_FLAG} -parallel -fp-model fast=1") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -parallel -fp-model fast=1") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -parallel -fp-model fast=1") + endif() + + set(CMAKE_CXX_FLAGS_DEBUG "-O0 ${CMAKE_CXX_FLAGS_DEBUG}") + set(CMAKE_C_FLAGS_DEBUG "-O0 ${CMAKE_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_RELEASE "-O3 ${CMAKE_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS_RELEASE "-O3 ${CMAKE_C_FLAGS_RELEASE}") - set(CMAKE_CXX_FLAGS_RELEASESSE2 "-O3 ${CMAKE_CXX_FLAGS_RELEASESSE2}") - set(CMAKE_C_FLAGS_RELEASESSE2 "-O3 ${CMAKE_C_FLAGS_RELEASESSE2}") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_C_FLAGS_RELWITHDEBINFO}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_C_FLAGS_RELWITHDEBINFO}") endif (LINUX) @@ -233,27 +273,32 @@ if (DARWIN) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mlong-branch") # NOTE: it's critical that the optimization flag is put in front. # NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered. - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -O3 -msse2 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -O3 -msse2 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") endif (DARWIN) if (LINUX OR DARWIN) - set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs") - - if (NOT GCC_DISABLE_FATAL_WARNINGS) - set(GCC_WARNINGS "${GCC_WARNINGS} -Werror") - endif (NOT GCC_DISABLE_FATAL_WARNINGS) - - set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor -Woverloaded-virtual") - - set(CMAKE_C_FLAGS "${GCC_WARNINGS} ${CMAKE_C_FLAGS}") - set(CMAKE_CXX_FLAGS "${GCC_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}") + if(${CMAKE_C_COMPILER} MATCHES "gcc*") + set(UNIX_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs") + set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor -Woverloaded-virtual") + elseif(${CMAKE_C_COMPILER} MATCHES "clang*") + set(UNIX_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-tautological-compare -Wno-char-subscripts -Wno-gnu -Wno-logical-op-parentheses -Wno-non-virtual-dtor ") + set(UNIX_WARNINGS "${UNIX_WARNINGS} -Woverloaded-virtual -Wno-parentheses-equality -Wno-reorder -Wno-unused-function -Wno-unused-value -Wno-unused-variable") + set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS}") + elseif(${CMAKE_C_COMPILER} MATCHES "icc") + set(UNIX_WARNINGS "-wd327 -wd597 -wd858") + set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS}") + endif() + + if (NOT DISABLE_FATAL_WARNINGS) + set(UNIX_WARNINGS "${UNIX_WARNINGS} -Werror") + endif (NOT DISABLE_FATAL_WARNINGS) + set(CMAKE_C_FLAGS "${UNIX_WARNINGS} ${CMAKE_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${UNIX_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}") if (WORD_SIZE EQUAL 32) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") @@ -279,20 +324,25 @@ else (STANDALONE) endif (STANDALONE) if(1 EQUAL 1) - add_definitions(-DOPENSIM_RULES=1) - add_definitions(-DMESH_ENABLED=1) + add_definitions(-DOPENSIM_RULES=1) + add_definitions(-DMESH_ENABLED=1) + add_definitions(-DENABLE_CLASSIC_CLOUDS=1) + if (NOT "$ENV{SHY_MOD}" STREQUAL "") + add_definitions(-DSHY_MOD=1) + endif (NOT "$ENV{SHY_MOD}" STREQUAL "") endif(1 EQUAL 1) -SET( CMAKE_EXE_LINKER_FLAGS_RELEASESSE2 +SET( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}" CACHE STRING - "Flags used for linking binaries under SSE2 build." + "Flags used for linking binaries under build." FORCE ) -SET( CMAKE_SHARED_LINKER_FLAGS_RELEASESSE2 +SET( CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}" CACHE STRING - "Flags used by the shared libraries linker under SSE2 build." + "Flags used by the shared libraries linker under build." FORCE ) MARK_AS_ADVANCED( - CMAKE_CXX_FLAGS_RELEASESSE2 - CMAKE_C_FLAGS_RELEASESSE2 - CMAKE_EXE_LINKER_FLAGS_RELEASESSE2 - CMAKE_SHARED_LINKER_FLAGS_RELEASESSE2 ) + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_FLAGS_RELEASE + CMAKE_EXE_LINKER_FLAGS_RELEASE + CMAKE_SHARED_LINKER_FLAGS_RELEASE + ) diff --git a/indra/cmake/Audio.cmake b/indra/cmake/Audio.cmake index d23bc2f9c..6bad4a726 100644 --- a/indra/cmake/Audio.cmake +++ b/indra/cmake/Audio.cmake @@ -9,7 +9,7 @@ if (STANDALONE) pkg_check_modules(VORBISFILE REQUIRED vorbisfile) else (STANDALONE) use_prebuilt_binary(ogg-vorbis) - set(VORBIS_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) + set(VORBIS_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) set(VORBISENC_INCLUDE_DIRS ${VORBIS_INCLUDE_DIRS}) set(VORBISFILE_INCLUDE_DIRS ${VORBIS_INCLUDE_DIRS}) diff --git a/indra/cmake/BerkeleyDB.cmake b/indra/cmake/BerkeleyDB.cmake index e3ca0fd77..032dd510e 100644 --- a/indra/cmake/BerkeleyDB.cmake +++ b/indra/cmake/BerkeleyDB.cmake @@ -1,4 +1,4 @@ -# -*- cmake -*- +include(Prebuilt) set(DB_FIND_QUIETLY ON) set(DB_FIND_REQUIRED ON) @@ -8,9 +8,10 @@ if (STANDALONE) else (STANDALONE) if (LINUX) # Need to add dependency pthread explicitely to support ld.gold. - set(DB_LIBRARIES db-4.2 pthread) + use_prebuilt_binary(db) + set(DB_LIBRARIES db-5.1 pthread) else (LINUX) set(DB_LIBRARIES db-4.2) endif (LINUX) - set(DB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) + set(DB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) endif (STANDALONE) diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake index 1275d0547..6babb05fd 100644 --- a/indra/cmake/Boost.cmake +++ b/indra/cmake/Boost.cmake @@ -13,7 +13,7 @@ if (STANDALONE) set(BOOST_SYSTEM_LIBRARY boost_system-mt) else (STANDALONE) use_prebuilt_binary(boost) - set(Boost_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) + set(Boost_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) if (WINDOWS) set(BOOST_VERSION 1_45) diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 28a3d5e4f..21eee45ac 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -29,17 +29,16 @@ set(cmake_SOURCE_FILES FindELFIO.cmake FindGooglePerfTools.cmake FindHunSpell.cmake - FindMono.cmake FindMT.cmake - FindMySQL.cmake FindNDOF.cmake FindOpenJPEG.cmake FindXmlRpcEpi.cmake - FMOD.cmake + FMOD.cmake + FMODEX.cmake FreeType.cmake GStreamer010Plugin.cmake GooglePerfTools.cmake - HUNSPELL.cmake + Hunspell.cmake JPEG.cmake LLAddBuildTest.cmake LLAudio.cmake @@ -63,8 +62,6 @@ set(cmake_SOURCE_FILES LLXML.cmake LScript.cmake Linking.cmake - MonoEmbed.cmake - MySQL.cmake NDOF.cmake OPENAL.cmake OpenGL.cmake @@ -83,10 +80,6 @@ set(cmake_SOURCE_FILES ZLIB.cmake ) -if(FMODEX) - list(APPEND cmake_SOURCE_FILES FMODEX.cmake) -endif(FMODEX) - source_group("Shared Rules" FILES ${cmake_SOURCE_FILES}) set(master_SOURCE_FILES diff --git a/indra/cmake/CopyWinLibs.cmake b/indra/cmake/CopyWinLibs.cmake index 21fe3f246..aa345e9cc 100644 --- a/indra/cmake/CopyWinLibs.cmake +++ b/indra/cmake/CopyWinLibs.cmake @@ -29,6 +29,8 @@ set(debug_files libapr-1.dll libaprutil-1.dll libapriconv-1.dll + libeay32.dll + ssleay32.dll ) copy_if_different( @@ -43,10 +45,6 @@ set(all_targets ${all_targets} ${out_targets}) set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") set(plugintest_debug_files libeay32.dll - libglib-2.0-0.dll - libgmodule-2.0-0.dll - libgobject-2.0-0.dll - libgthread-2.0-0.dll qtcored4.dll qtguid4.dll qtnetworkd4.dll @@ -92,11 +90,6 @@ set(all_targets ${all_targets} ${out_targets}) set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") set(plugintest_release_files libeay32.dll - libglib-2.0-0.dll - libgmodule-2.0-0.dll - libgobject-2.0-0.dll - libgthread-2.0-0.dll -# llkdu.dll (not required for plugin test) qtcore4.dll qtgui4.dll qtnetwork4.dll @@ -112,14 +105,6 @@ copy_if_different( ) set(all_targets ${all_targets} ${out_targets}) -copy_if_different( - ${plugintest_release_src_dir} - "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/ReleaseSSE2" - out_targets - ${plugintest_release_files} - ) -set(all_targets ${all_targets} ${out_targets}) - copy_if_different( ${plugintest_release_src_dir} "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/RelWithDebInfo" @@ -146,14 +131,6 @@ copy_if_different( ) set(all_targets ${all_targets} ${out_targets}) -copy_if_different( - ${plugintest_release_src_dir} - "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/ReleaseSSE2/imageformats" - out_targets - ${plugintest_release_files} - ) -set(all_targets ${all_targets} ${out_targets}) - copy_if_different( ${plugintest_release_src_dir} "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/RelWithDebInfo/imageformats" @@ -170,14 +147,6 @@ copy_if_different( ) set(all_targets ${all_targets} ${out_targets}) -copy_if_different( - ${plugintest_release_src_dir} - "${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2/llplugin/imageformats" - out_targets - ${plugintest_release_files} - ) -set(all_targets ${all_targets} ${out_targets}) - copy_if_different( ${plugintest_release_src_dir} "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin/imageformats" @@ -224,14 +193,6 @@ copy_if_different( ) set(all_targets ${all_targets} ${out_targets}) -copy_if_different( - ${plugins_release_src_dir} - "${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2/llplugin" - out_targets - ${plugins_release_files} - ) -set(all_targets ${all_targets} ${out_targets}) - copy_if_different( ${plugins_release_src_dir} "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin" @@ -247,46 +208,44 @@ set(release_files libapr-1.dll libaprutil-1.dll libapriconv-1.dll + libeay32.dll + ssleay32.dll ) if(FMODEX) - find_path(FMODEX_BINARY_DIR fmodex.dll + find_path(FMODEX_BINARY_DIR fmodex.dll ${release_src_dir} ${FMODEX_SDK_DIR}/api ${FMODEX_SDK_DIR} ) - if(FMODEX_BINARY_DIR) - copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Release" out_targets fmodex.dll) - set(all_targets ${all_targets} ${out_targets}) - copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2" out_targets fmodex.dll) - set(all_targets ${all_targets} ${out_targets}) - copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" out_targets fmodex.dll) - set(all_targets ${all_targets} ${out_targets}) - copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Debug" out_targets fmodex.dll) - set(all_targets ${all_targets} ${out_targets}) - endif(FMODEX_BINARY_DIR) + if(FMODEX_BINARY_DIR) + copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Release" out_targets fmodex.dll) + set(all_targets ${all_targets} ${out_targets}) + copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" out_targets fmodex.dll) + set(all_targets ${all_targets} ${out_targets}) + copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Debug" out_targets fmodex.dll) + set(all_targets ${all_targets} ${out_targets}) + endif(FMODEX_BINARY_DIR) endif(FMODEX) if(FMOD) - find_path(FMOD_BINARY_DIR fmod.dll + find_path(FMOD_BINARY_DIR fmod.dll ${release_src_dir} ${FMOD_SDK_DIR}/api ${FMOD_SDK_DIR} ) - if(FMOD_BINARY_DIR) - copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Release" out_targets fmod.dll) - set(all_targets ${all_targets} ${out_targets}) - copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2" out_targets fmod.dll) - set(all_targets ${all_targets} ${out_targets}) - copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" out_targets fmod.dll) - set(all_targets ${all_targets} ${out_targets}) - copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Debug" out_targets fmod.dll) - set(all_targets ${all_targets} ${out_targets}) - else(FMOD_BINARY_DIR) - list(APPEND release_files fmod.dll) #Required for compile. This will cause an error in copying binaries. - endif(FMOD_BINARY_DIR) +if(FMOD_BINARY_DIR) + copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Release" out_targets fmod.dll) + set(all_targets ${all_targets} ${out_targets}) + copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" out_targets fmod.dll) + set(all_targets ${all_targets} ${out_targets}) + copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Debug" out_targets fmod.dll) + set(all_targets ${all_targets} ${out_targets}) + else(FMOD_BINARY_DIR) + list(APPEND release_files fmod.dll) #Required for compile. This will cause an error in copying binaries. + endif(FMOD_BINARY_DIR) endif(FMOD) copy_if_different( @@ -305,22 +264,6 @@ copy_if_different( ) set(all_targets ${all_targets} ${out_targets}) -copy_if_different( - ${release_src_dir} - "${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2" - out_targets - ${release_files} - ) -set(all_targets ${all_targets} ${out_targets}) - -copy_if_different( - ${vivox_src_dir} - "${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2" - out_targets - ${vivox_files} - ) -set(all_targets ${all_targets} ${out_targets}) - copy_if_different( ${release_src_dir} "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" @@ -371,15 +314,6 @@ else(EXISTS ${internal_llkdu_path}) COMMENT "Copying llkdu.dll ${CMAKE_CURRENT_BINARY_DIR}/Release" ) set(all_targets ${all_targets} ${release_llkdu_dst}) - - set(releasesse2_llkdu_dst "${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2/llkdu.dll") - ADD_CUSTOM_COMMAND( - OUTPUT ${releasesse2_llkdu_dst} - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${release_llkdu_src} ${releasesse2_llkdu_dst} - DEPENDS ${release_llkdu_src} - COMMENT "Copying llkdu.dll ${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2" - ) - set(all_targets ${all_targets} ${releasesse2_llkdu_dst}) set(relwithdebinfo_llkdu_dst "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llkdu.dll") ADD_CUSTOM_COMMAND( @@ -455,14 +389,6 @@ if (MSVC80) ) set(all_targets ${all_targets} ${out_targets}) - copy_if_different( - ${release_msvc8_redist_path} - "${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2" - out_targets - ${release_msvc8_files} - ) - set(all_targets ${all_targets} ${out_targets}) - copy_if_different( ${release_msvc8_redist_path} "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" @@ -483,19 +409,6 @@ if (MSVC80) DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Release/Microsoft.VC80.CRT.manifest COMMENT "Creating release app config file" ) - - set(releasesse2_appconfig_file ${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2/${VIEWER_BINARY_NAME}.exe.config) - add_custom_command( - OUTPUT ${releasesse2_appconfig_file} - COMMAND ${PYTHON_EXECUTABLE} - ARGS - ${CMAKE_CURRENT_SOURCE_DIR}/build_win32_appConfig.py - ${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2/Microsoft.VC80.CRT.manifest - ${CMAKE_CURRENT_SOURCE_DIR}/SecondLife.exe.config - ${releasesse2_appconfig_file} - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2/Microsoft.VC80.CRT.manifest - COMMENT "Creating release-sse2 app config file" - ) set(relwithdebinfo_appconfig_file ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/${VIEWER_BINARY_NAME}.exe.config) add_custom_command( @@ -517,7 +430,6 @@ add_custom_target(copy_win_libs ALL DEPENDS ${all_targets} ${release_appconfig_file} - ${releasesse2_appconfig_file} ${relwithdebinfo_appconfig_file} ${debug_appconfig_file} ) diff --git a/indra/cmake/DBusGlib.cmake b/indra/cmake/DBusGlib.cmake index b78a0b1e7..05266eb9c 100644 --- a/indra/cmake/DBusGlib.cmake +++ b/indra/cmake/DBusGlib.cmake @@ -7,15 +7,14 @@ if (STANDALONE) pkg_check_modules(DBUSGLIB REQUIRED dbus-glib-1) elseif (LINUX) - use_prebuilt_binary(glib) # dbusglib needs glib use_prebuilt_binary(dbusglib) set(DBUSGLIB_FOUND ON FORCE BOOL) set(DBUSGLIB_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0 + ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/dbus ) - + # We don't need to explicitly link against dbus-glib itself, because + # the viewer probes for the system's copy at runtime. set(DBUSGLIB_LIBRARIES - dbus-glib-1 gobject-2.0 glib-2.0 ) diff --git a/indra/cmake/ELFIO.cmake b/indra/cmake/ELFIO.cmake index e51993b0f..fbde78311 100644 --- a/indra/cmake/ELFIO.cmake +++ b/indra/cmake/ELFIO.cmake @@ -8,7 +8,7 @@ if (STANDALONE) elseif (LINUX) use_prebuilt_binary(elfio) set(ELFIO_LIBRARIES ELFIO) - set(ELFIO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) + set(ELFIO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) set(ELFIO_FOUND "YES") endif (STANDALONE) diff --git a/indra/cmake/EXPAT.cmake b/indra/cmake/EXPAT.cmake index acb15dc62..8a8f84526 100644 --- a/indra/cmake/EXPAT.cmake +++ b/indra/cmake/EXPAT.cmake @@ -13,5 +13,5 @@ else (STANDALONE) else (WINDOWS) set(EXPAT_LIBRARIES expat) endif (WINDOWS) - set(EXPAT_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) + set(EXPAT_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) endif (STANDALONE) diff --git a/indra/cmake/FindJsonCpp.cmake b/indra/cmake/FindJsonCpp.cmake index 7dfc2b097..44ab0e769 100644 --- a/indra/cmake/FindJsonCpp.cmake +++ b/indra/cmake/FindJsonCpp.cmake @@ -24,8 +24,8 @@ EXEC_PROGRAM(${CMAKE_CXX_COMPILER} # Try to find a library that was compiled with the same compiler version as we currently use. SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson_linux-gcc-${_gcc_COMPILER_VERSION}_libmt.so) IF (STANDALONE) - # On standalone, assume that the system installed library was compiled with the used compiler. - SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson.so) + # On standalone, assume that the system installed library was compiled with the used compiler. + SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson.so) ENDIF (STANDALONE) FIND_LIBRARY(JSONCPP_LIBRARY NAMES ${JSONCPP_NAMES} diff --git a/indra/cmake/FindLLQtWebkit.cmake b/indra/cmake/FindLLQtWebkit.cmake index c747ec32a..731ae67d7 100644 --- a/indra/cmake/FindLLQtWebkit.cmake +++ b/indra/cmake/FindLLQtWebkit.cmake @@ -35,7 +35,7 @@ find_path(LLQTWEBKIT_INCLUDE_DIR llqtwebkit.h NO_SYSTEM_ENVIRONMENT_PATH HINTS $ find_library(LLQTWEBKIT_LIBRARY NAMES llqtwebkit NO_SYSTEM_ENVIRONMENT_PATH HINTS ${LLQTWEBKIT_LIBRARY_DIRS}) -if (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) # If pkg-config couldn't find it, pretend we don't have pkg-config. +if (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) # If pkg-config couldn't find it, pretend we don't have pkg-config. set(LLQTWEBKIT_LIBRARIES llqtwebkit) get_filename_component(LLQTWEBKIT_LIBRARY_DIRS ${LLQTWEBKIT_LIBRARY} PATH) endif (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) diff --git a/indra/cmake/FindMT.cmake b/indra/cmake/FindMT.cmake index 71b5a43e5..babc68db5 100644 --- a/indra/cmake/FindMT.cmake +++ b/indra/cmake/FindMT.cmake @@ -1,17 +1,17 @@ -#Find the windows manifest tool. -if (MSVC80) - FIND_PROGRAM(HAVE_MANIFEST_TOOL NAMES mt - PATHS - "$ENV{PROGRAMFILES}/Microsoft Visual Studio 8/VC/bin" - "$ENV{PROGRAMFILES}/Microsoft Visual Studio 8/Common7/Tools/Bin" - "$ENV{PROGRAMFILES}/Microsoft Visual Studio 8/SDK/v2.0/Bin") - IF(HAVE_MANIFEST_TOOL) - MESSAGE(STATUS "Found Mainfest Tool. Embedding custom manifests.") - ELSE(HAVE_MANIFEST_TOOL) - MESSAGE(FATAL_ERROR "Manifest tool, mt.exe, can't be found.") - ENDIF(HAVE_MANIFEST_TOOL) - - STRING(REPLACE "/MANIFEST " "/MANIFEST:NO" CMAKE_EXE_LINKER_FLAGS - ${CMAKE_EXE_LINKER_FLAGS}) - -endif (MSVC80) +#Find the windows manifest tool. +if (MSVC80) + FIND_PROGRAM(HAVE_MANIFEST_TOOL NAMES mt + PATHS + "$ENV{PROGRAMFILES}/Microsoft Visual Studio 8/VC/bin" + "$ENV{PROGRAMFILES}/Microsoft Visual Studio 8/Common7/Tools/Bin" + "$ENV{PROGRAMFILES}/Microsoft Visual Studio 8/SDK/v2.0/Bin") + IF(HAVE_MANIFEST_TOOL) + MESSAGE(STATUS "Found Mainfest Tool. Embedding custom manifests.") + ELSE(HAVE_MANIFEST_TOOL) + MESSAGE(FATAL_ERROR "Manifest tool, mt.exe, can't be found.") + ENDIF(HAVE_MANIFEST_TOOL) + + STRING(REPLACE "/MANIFEST " "/MANIFEST:NO" CMAKE_EXE_LINKER_FLAGS + ${CMAKE_EXE_LINKER_FLAGS}) + +endif (MSVC80) diff --git a/indra/cmake/FindMono.cmake b/indra/cmake/FindMono.cmake deleted file mode 100644 index c36d7259e..000000000 --- a/indra/cmake/FindMono.cmake +++ /dev/null @@ -1,68 +0,0 @@ -# - Try to find the mono, mcs, gmcs and gacutil -# -# defines -# -# MONO_FOUND - system has mono, mcs, gmcs and gacutil -# MONO_PATH - where to find 'mono' -# MCS_PATH - where to find 'mcs' -# GMCS_PATH - where to find 'gmcs' -# GACUTIL_PATH - where to find 'gacutil' -# -# copyright (c) 2007 Arno Rehn arno@arnorehn.de -# -# Redistribution and use is allowed according to the terms of the GPL license. -# Removed the check for gmcs - -FIND_PROGRAM (MONO_EXECUTABLE mono - "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" - "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" - /bin - /usr/bin - /usr/local/bin -) -FIND_PROGRAM (MCS_EXECUTABLE mcs - "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" - "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" - /bin - /usr/bin - /usr/local/bin -) -FIND_PROGRAM (GMCS_EXECUTABLE gmcs - "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" - "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" - /bin - /usr/bin - /usr/local/bin -) -FIND_PROGRAM (GACUTIL_EXECUTABLE gacutil - "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" - "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" - /bin - /usr/bin - /usr/local/bin -) -FIND_PROGRAM (ILASM_EXECUTABLE - ilasm - NO_DEFAULT_PATH - PATHS "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" /bin /usr/bin /usr/local/bin -) - -SET (MONO_FOUND FALSE) - -IF (MONO_EXECUTABLE AND MCS_EXECUTABLE AND GACUTIL_EXECUTABLE) - SET (MONO_FOUND TRUE) -ENDIF (MONO_EXECUTABLE AND MCS_EXECUTABLE AND GACUTIL_EXECUTABLE) - -IF (MONO_FOUND) - IF (NOT Mono_FIND_QUIETLY) - MESSAGE(STATUS "Found mono: ${MONO_EXECUTABLE}") - MESSAGE(STATUS "Found mcs: ${MCS_EXECUTABLE}") - MESSAGE(STATUS "Found gacutil: ${GACUTIL_EXECUTABLE}") - ENDIF (NOT Mono_FIND_QUIETLY) -ELSE (MONO_FOUND) - IF (Mono_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find one or more of the following programs: mono, mcs, gacutil") - ENDIF (Mono_FIND_REQUIRED) -ENDIF (MONO_FOUND) - -MARK_AS_ADVANCED(MONO_EXECUTABLE MCS_EXECUTABLE GACUTIL_EXECUTABLE) diff --git a/indra/cmake/FindMySQL.cmake b/indra/cmake/FindMySQL.cmake deleted file mode 100644 index 431940328..000000000 --- a/indra/cmake/FindMySQL.cmake +++ /dev/null @@ -1,48 +0,0 @@ -# -*- cmake -*- - -# - Find MySQL -# Find the MySQL includes and library -# This module defines -# MYSQL_INCLUDE_DIR, where to find mysql.h, etc. -# MYSQL_LIBRARIES, the libraries needed to use Mysql. -# MYSQL_FOUND, If false, do not try to use Mysql. -# also defined, but not for general use are -# MYSQL_LIBRARY, where to find the Mysql library. - -FIND_PATH(MYSQL_INCLUDE_DIR mysql/mysql.h -/usr/local/include -/usr/include -) - -SET(MYSQL_NAMES ${MYSQL_NAMES} mysqlclient) -FIND_LIBRARY(MYSQL_LIBRARY - NAMES ${MYSQL_NAMES} - PATHS /usr/lib/mysql /usr/lib /usr/local/lib/mysql /usr/local/lib - ) - -IF (MYSQL_LIBRARY AND MYSQL_INCLUDE_DIR) - SET(MYSQL_LIBRARIES ${MYSQL_LIBRARY}) - SET(MYSQL_FOUND "YES") -ELSE (MYSQL_LIBRARY AND MYSQL_INCLUDE_DIR) - SET(MYSQL_FOUND "NO") -ENDIF (MYSQL_LIBRARY AND MYSQL_INCLUDE_DIR) - - -IF (MYSQL_FOUND) - IF (NOT MYSQL_FIND_QUIETLY) - MESSAGE(STATUS "Found MySQL: ${MYSQL_LIBRARIES}") - ENDIF (NOT MYSQL_FIND_QUIETLY) -ELSE (MYSQL_FOUND) - IF (MYSQL_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find MySQL library") - ENDIF (MYSQL_FIND_REQUIRED) -ENDIF (MYSQL_FOUND) - -# Deprecated declarations. -SET (NATIVE_MYSQL_INCLUDE_PATH ${MYSQL_INCLUDE_DIR} ) -GET_FILENAME_COMPONENT (NATIVE_MYSQL_LIB_PATH ${MYSQL_LIBRARY} PATH) - -MARK_AS_ADVANCED( - MYSQL_LIBRARY - MYSQL_INCLUDE_DIR - ) diff --git a/indra/cmake/FreeType.cmake b/indra/cmake/FreeType.cmake index 5f1aa26e8..e9d4d8093 100644 --- a/indra/cmake/FreeType.cmake +++ b/indra/cmake/FreeType.cmake @@ -11,7 +11,7 @@ else (STANDALONE) set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) else (LINUX) - set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) + set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) endif (LINUX) set(FREETYPE_LIBRARIES freetype) diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index fc5b40d42..8fbe08dc2 100644 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -5,7 +5,7 @@ if (STANDALONE) include(FindGooglePerfTools) else (STANDALONE) if (LINUX OR WINDOWS) - use_prebuilt_binary(google) + use_prebuilt_binary(gperftools) endif (LINUX OR WINDOWS) if (WINDOWS) set(TCMALLOC_LIBRARIES libtcmalloc_minimal.lib) diff --git a/indra/cmake/HUNSPELL.cmake b/indra/cmake/Hunspell.cmake similarity index 88% rename from indra/cmake/HUNSPELL.cmake rename to indra/cmake/Hunspell.cmake index cd5d7e00b..365df6783 100644 --- a/indra/cmake/HUNSPELL.cmake +++ b/indra/cmake/Hunspell.cmake @@ -9,7 +9,7 @@ else (STANDALONE) set(HUNSPELL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/hunspell) if (LINUX OR DARWIN) - set(HUNSPELL_LIBRARY hunspell-1.2) + set(HUNSPELL_LIBRARY hunspell-1.3) else (LINUX OR DARWIN) set(HUNSPELL_LIBRARY libhunspell) endif (LINUX OR DARWIN) diff --git a/indra/cmake/JPEG.cmake b/indra/cmake/JPEG.cmake index 9514d59f6..f3e5753a6 100644 --- a/indra/cmake/JPEG.cmake +++ b/indra/cmake/JPEG.cmake @@ -19,5 +19,5 @@ else (STANDALONE) elseif (WINDOWS) set(JPEG_LIBRARIES jpeglib) endif (LINUX) - set(JPEG_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) + set(JPEG_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) endif (STANDALONE) diff --git a/indra/cmake/JsonCpp.cmake b/indra/cmake/JsonCpp.cmake index 552fc19fc..856034955 100644 --- a/indra/cmake/JsonCpp.cmake +++ b/indra/cmake/JsonCpp.cmake @@ -18,5 +18,5 @@ else (STANDALONE) elseif (LINUX) set(JSONCPP_LIBRARIES jsoncpp) endif (WINDOWS) - set(JSONCPP_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/jsoncpp) + set(JSONCPP_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/jsoncpp) endif (STANDALONE) diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake index 5cf92335e..f8d2a2902 100644 --- a/indra/cmake/LLWindow.cmake +++ b/indra/cmake/LLWindow.cmake @@ -13,15 +13,13 @@ if (STANDALONE) SDL_LIBRARY ) else (STANDALONE) - if (NOT DARWIN) + if (LINUX) use_prebuilt_binary(mesa) - endif (NOT DARWIN) - if (LINUX AND VIEWER) use_prebuilt_binary(SDL) set (SDL_FOUND TRUE) - set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux) - set (SDL_LIBRARY SDL) - endif (LINUX AND VIEWER) + set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}) + set (SDL_LIBRARY SDL directfb fusion direct) + endif (LINUX) endif (STANDALONE) if (SDL_FOUND) diff --git a/indra/cmake/LLXUIXML.cmake b/indra/cmake/LLXUIXML.cmake new file mode 100644 index 000000000..b8bfe48c7 --- /dev/null +++ b/indra/cmake/LLXUIXML.cmake @@ -0,0 +1,7 @@ +# -*- cmake -*- + +set(LLXUIXML_INCLUDE_DIRS + ${LIBS_OPEN_DIR}/llxuixml + ) + +set(LLXUIXML_LIBRARIES llxuixml) diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index eaa8a6dc2..70d005d33 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -6,11 +6,7 @@ if (NOT STANDALONE) set(ARCH_PREBUILT_DIRS_RELEASE ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib/release) set(ARCH_PREBUILT_DIRS_DEBUG ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib/debug) elseif (LINUX) - if (VIEWER) - set(ARCH_PREBUILT_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib_release_client) - else (VIEWER) - set(ARCH_PREBUILT_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib_release) - endif (VIEWER) + set(ARCH_PREBUILT_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib/release) set(ARCH_PREBUILT_DIRS_RELEASE ${ARCH_PREBUILT_DIRS}) set(ARCH_PREBUILT_DIRS_DEBUG ${ARCH_PREBUILT_DIRS}) elseif (DARWIN) diff --git a/indra/cmake/MonoDeps.cmake b/indra/cmake/MonoDeps.cmake deleted file mode 100644 index 52d549156..000000000 --- a/indra/cmake/MonoDeps.cmake +++ /dev/null @@ -1,48 +0,0 @@ -# -*- cmake -*- - -set(MONO_PREBUILT_LIBRARIES_DIR ${LIBS_PREBUILT_DIR}/mono/1.0) - -set(MONO_PREBUILT_LIBRARIES - Iesi.Collections.dll - Iesi.Collections.pdb - Mono.CompilerServices.SymbolWriter.dll - Mono.PEToolkit.dll - Mono.PEToolkit.pdb - Mono.Security.dll - PEAPI.dll - RAIL.dll - RAIL.pdb - ) - - set(MONO_CORE_LIBRARIES - System.dll - System.Xml.dll - mscorlib.dll) - -if(WINDOWS) - set(MONO_DEPENDENCIES - DomainCreator - DomainRegister - LslLibrary - LslUserScript - Script - ScriptTypes - TestFormat - UserScript - UThread - UThreadInjector - ) -else(WINDOWS) - set(MONO_DEPENDENCIES - DomainCreator_POST_BUILD - DomainRegister_POST_BUILD - LslLibrary_POST_BUILD - LslUserScript_POST_BUILD - Script_POST_BUILD - ScriptTypes_POST_BUILD - TestFormat_POST_BUILD - UserScript_POST_BUILD - UThread_POST_BUILD - UThreadInjector_POST_BUILD - ) -endif(WINDOWS) diff --git a/indra/cmake/MonoEmbed.cmake b/indra/cmake/MonoEmbed.cmake deleted file mode 100644 index 0f1f23309..000000000 --- a/indra/cmake/MonoEmbed.cmake +++ /dev/null @@ -1,57 +0,0 @@ -# -*- cmake -*- - -include(Prebuilt) -use_prebuilt_binary(libmono) - -SET(GLIB_2_0 glib-2.0) - -if (WINDOWS) - SET(MONO_LIB mono) -else (WINDOWS) - SET(MONO_LIB mono) - SET(M_LIBRARIES m) - SET(GTHREAD_2_0 gthread-2.0) -endif(WINDOWS) - - -IF (DARWIN) - - FIND_LIBRARY(MONO_LIBRARY NAMES Mono) - # Find_file doesnt work as expected. Hardcode relative to Mono.framework. - #FIND_FILE(GLIB_CONFIG glibconfig.h ${MONO_LIBRARY}) - #FIND_FILE(MONO_GLIB_LIBRARY glib.h ${MONO_LIBRARY}) - SET(MONO_GLIB_LIBRARY ${MONO_LIBRARY}/Headers/glib-2.0/) - SET(GLIB_CONFIG ${MONO_LIBRARY}/Libraries/glib-2.0/include/) - SET(MONO_LIB_DIRECTORY ${MONO_LIBRARY}/Libraries) - - IF (MONO_LIBRARY AND MONO_GLIB_LIBRARY AND GLIB_CONFIG) - MESSAGE(STATUS "Found Mono for embedding") - INCLUDE_DIRECTORIES(${MONO_GLIB_LIBRARY} ${GLIB_CONFIG}) - LINK_DIRECTORIES(${MONO_LIB_DIRECTORY}) - ELSE (MONO_LIBRARY AND MONO_GLIB_LIBRARY AND GLIB_CONFIG) - MESSAGE(FATAL_ERROR "Mono not found for embedding") - MESSAGE(${MONO_LIBRARY}) - MESSAGE(${MONO_GLIB_LIBRARY}) - MESSAGE(${GLIB_CONFIG}) - ENDIF (MONO_LIBRARY AND MONO_GLIB_LIBRARY AND GLIB_CONFIG) - -ELSE (DARWIN) - - SET(MONO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) - SET(GLIB_2_0_PLATFORM_INCLUDE_DIR - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0) - SET(GLIB_2_0_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/glib-2.0) - - INCLUDE_DIRECTORIES( - ${MONO_INCLUDE_DIR} - ${GLIB_2_0_PLATFORM_INCLUDE_DIR} - ${GLIB_2_0_INCLUDE_DIR}) - -ENDIF (DARWIN) - -SET(MONO_LIBRARIES - ${MONO_LIB} - ${M_LIBRARIES} - ${GLIB_2_0} - ${GTHREAD_2_0} -) diff --git a/indra/cmake/MySQL.cmake b/indra/cmake/MySQL.cmake deleted file mode 100644 index e591fbc3d..000000000 --- a/indra/cmake/MySQL.cmake +++ /dev/null @@ -1,26 +0,0 @@ -# -*- cmake -*- -include(Linking) -include(Prebuilt) - -use_prebuilt_binary(mysql) - -if (LINUX) - if (WORD_SIZE EQUAL 32 OR DEBIAN_VERSION STREQUAL "3.1") - set(MYSQL_LIBRARIES mysqlclient) - set(MYSQL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) - else (WORD_SIZE EQUAL 32 OR DEBIAN_VERSION STREQUAL "3.1") - # Use the native MySQL library on a 64-bit system. - set(MYSQL_FIND_QUIETLY ON) - set(MYSQL_FIND_REQUIRED ON) - include(FindMySQL) - endif (WORD_SIZE EQUAL 32 OR DEBIAN_VERSION STREQUAL "3.1") -elseif (WINDOWS) - set(MYSQL_LIBRARIES mysqlclient) - set(MYSQL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) -elseif (DARWIN) - set(MYSQL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) - set(MYSQL_LIBRARIES - optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libmysqlclient.a - debug ${ARCH_PREBUILT_DIRS_DEBUG}/libmysqlclient.a - ) -endif (LINUX) diff --git a/indra/cmake/NDOF.cmake b/indra/cmake/NDOF.cmake index bdf5db130..a4e210405 100644 --- a/indra/cmake/NDOF.cmake +++ b/indra/cmake/NDOF.cmake @@ -15,7 +15,7 @@ else (STANDALONE) set(NDOF_LIBRARY ndofdev) endif (WINDOWS) - set(NDOF_INCLUDE_DIR ${ARCH_PREBUILT_DIRS}/include/ndofdev) + set(NDOF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/ndofdev) set(NDOF_FOUND 1) endif (STANDALONE) diff --git a/indra/cmake/OPENAL.cmake b/indra/cmake/OPENAL.cmake index d01c680ed..d5ab802d9 100644 --- a/indra/cmake/OPENAL.cmake +++ b/indra/cmake/OPENAL.cmake @@ -21,6 +21,7 @@ if (OPENAL) openal alut ) + set(OPENAL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) endif (OPENAL) if (OPENAL) diff --git a/indra/cmake/OpenGL.cmake b/indra/cmake/OpenGL.cmake index 5ba730c4a..91d949409 100644 --- a/indra/cmake/OpenGL.cmake +++ b/indra/cmake/OpenGL.cmake @@ -6,5 +6,5 @@ if (NOT (STANDALONE OR DARWIN)) # possible glh_linear should have its own .cmake file instead #use_prebuilt_binary(glh_linear) # actually... not any longer, it's now in git -SG - set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) + set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) endif () diff --git a/indra/cmake/PNG.cmake b/indra/cmake/PNG.cmake index f075adaa0..269b54de7 100644 --- a/indra/cmake/PNG.cmake +++ b/indra/cmake/PNG.cmake @@ -10,8 +10,10 @@ else (STANDALONE) use_prebuilt_binary(libpng) if (WINDOWS) set(PNG_LIBRARIES libpng15) - else (WINDOWS) - set(PNG_LIBRARIES png12) - endif (WINDOWS) - set(PNG_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) + elseif(DARWIN) + set(PNG_LIBRARIES png15) + else(LINUX) + set(PNG_LIBRARIES png15) + endif() + set(PNG_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libpng15) endif (STANDALONE) diff --git a/indra/cmake/PulseAudio.cmake b/indra/cmake/PulseAudio.cmake old mode 100755 new mode 100644 index e918de019..dafdd4163 --- a/indra/cmake/PulseAudio.cmake +++ b/indra/cmake/PulseAudio.cmake @@ -13,7 +13,7 @@ if (PULSEAUDIO) use_prebuilt_binary(pulseaudio) set(PULSEAUDIO_FOUND ON FORCE BOOL) set(PULSEAUDIO_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/include + ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include ) # We don't need to explicitly link against pulseaudio itself, because # the viewer probes for the system's copy at runtime. diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake index 6cf3a43d2..679b5bf3a 100644 --- a/indra/cmake/UI.cmake +++ b/indra/cmake/UI.cmake @@ -31,11 +31,9 @@ if (STANDALONE) add_definitions(${${pkg}_CFLAGS_OTHERS}) endforeach(pkg) else (STANDALONE) - if (NOT DARWIN) + if (LINUX) use_prebuilt_binary(glib) # gtk-etc needs glib use_prebuilt_binary(gtk-atk-pango-glib) - endif (NOT DARWIN) - if (LINUX) set(UI_LIBRARIES atk-1.0 X11 @@ -60,7 +58,6 @@ else (STANDALONE) ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/cairo ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/pixman-1 - ${LIBS_PREBUILT_DIR}/include ) foreach(include ${${LL_ARCH}_INCLUDES}) include_directories(${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/${include}) diff --git a/indra/cmake/XmlRpcEpi.cmake b/indra/cmake/XmlRpcEpi.cmake index 56eb7e250..cbfe1e16f 100644 --- a/indra/cmake/XmlRpcEpi.cmake +++ b/indra/cmake/XmlRpcEpi.cmake @@ -9,5 +9,5 @@ if (STANDALONE) else (STANDALONE) use_prebuilt_binary(xmlrpc-epi) set(XMLRPCEPI_LIBRARIES xmlrpc-epi) - set(XMLRPCEPI_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) + set(XMLRPCEPI_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) endif (STANDALONE) diff --git a/indra/cmake/ZLIB.cmake b/indra/cmake/ZLIB.cmake index 48e5130ad..c133248be 100644 --- a/indra/cmake/ZLIB.cmake +++ b/indra/cmake/ZLIB.cmake @@ -17,6 +17,6 @@ else (STANDALONE) set(ZLIB_LIBRARIES z) endif (WINDOWS) if (WINDOWS OR LINUX) - set(ZLIB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/zlib) + set(ZLIB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/zlib) endif (WINDOWS OR LINUX) endif (STANDALONE) diff --git a/indra/develop.py b/indra/develop.py index d44db29c7..5e94ca125 100755 --- a/indra/develop.py +++ b/indra/develop.py @@ -70,7 +70,7 @@ def quote(opts): class PlatformSetup(object): generator = None build_types = {} - for t in ('Debug', 'Release', 'ReleaseSSE2', 'RelWithDebInfo'): + for t in ('Debug', 'Release', 'RelWithDebInfo'): build_types[t.lower()] = t build_type = build_types['relwithdebinfo'] @@ -764,7 +764,7 @@ Options: --unattended build unattended, do not invoke any tools requiring a human response --universal build a universal binary on Mac OS X (unsupported) - -t | --type=NAME build type ("Debug", "Release", "ReleaseSSE2", or "RelWithDebInfo") + -t | --type=NAME build type ("Debug", "Release", or "RelWithDebInfo") -m32 | -m64 build architecture (32-bit or 64-bit) -N | --no-distcc disable use of distcc -G | --generator=NAME generator name diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index 3e5e39efa..11945a239 100644 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -120,7 +120,7 @@ ARGUMENTS=[ On Linux this would try to use Linux_i686Manifest.""", default=""), dict(name='build', description='Build directory.', default=DEFAULT_SRCTREE), - dict(name='buildtype', description="""The build type used. ('Debug', 'Release', 'ReleaseSSE2' or 'RelWithDebInfo') + dict(name='buildtype', description="""The build type used. ('Debug', 'Release', or 'RelWithDebInfo') Default is Release """, default="Release"), dict(name='branding_id', description="""Identifier for the branding set to diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt index 44edde114..61c383c0d 100644 --- a/indra/llaudio/CMakeLists.txt +++ b/indra/llaudio/CMakeLists.txt @@ -5,27 +5,25 @@ project(llaudio) include(00-Common) include(Audio) include(LLAudio) -if(FMODEX) - include(FMODEX) - if(FMODEX) - set(FMOD OFF) - endif(FMODEX) -endif(FMODEX) -if(NOT FMODEX) - include(FMOD) -endif(NOT FMODEX) +if (FMODEX) + include(FMODEX) + set(FMOD OFF) +endif (FMODEX) +if (NOT FMODEX) + include(FMOD) +endif (NOT FMODEX) include(OPENAL) include(LLCommon) include(LLMath) include(LLMessage) include(LLVFS) -if(FMODEX) - include_directories(${FMODEX_INCLUDE_DIR}) +if (FMODEX) + include_directories(${FMODEX_INCLUDE_DIR}) endif(FMODEX) if(FMOD) - include_directories(${FMOD_INCLUDE_DIR}) -endif(FMOD) + include_directories(${FMOD_INCLUDE_DIR}) +endif (FMOD) include_directories( ${LLAUDIO_INCLUDE_DIRS} @@ -37,7 +35,7 @@ include_directories( ${VORBISENC_INCLUDE_DIRS} ${VORBISFILE_INCLUDE_DIRS} ${VORBIS_INCLUDE_DIRS} - ${OPENAL_LIB_INCLUDE_DIRS} + ${OPENAL_INCLUDE_DIRS} ${FREEAULT_LIB_INCLUDE_DIRS} ) diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index 4350152ac..5063cbe7a 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -168,19 +168,13 @@ long vfs_tell (void *datasource) return file->tell(); } -LLVorbisDecodeState::LLVorbisDecodeState(const LLUUID &uuid, const std::string &out_filename) -{ - mDone = FALSE; - mValid = FALSE; - mBytesRead = -1; - mUUID = uuid; - mInFilep = NULL; - mCurrentSection = 0; +LLVorbisDecodeState::LLVorbisDecodeState(const LLUUID &uuid, const std::string &out_filename) : + mValid(FALSE), mDone(FALSE), mBytesRead(-1), mUUID(uuid), #if !defined(USE_WAV_VFILE) - mOutFilename = out_filename; - mFileHandle = LLLFSThread::nullHandle(); + mOutFilename(out_filename), mFileHandle(LLLFSThread::nullHandle()), #endif - // No default value for mVF, it's an ogg structure? + mInFilep(NULL), mCurrentSection(0) +{ } LLVorbisDecodeState::~LLVorbisDecodeState() @@ -242,8 +236,8 @@ BOOL LLVorbisDecodeState::initDecode() llwarns << "No default bitstream found" << llendl; } // - // This magic value is equivilent to 150MiB of data. - // Prevents griffers from utilizin a huge xbox sound the size of god to instafry the viewer + // This magic value is equivalent to 150MiB of data. + // Prevents griefers from utilizing a huge xbox sound the size of god to instafry the viewer if(size_guess >= 157286400) { llwarns << "Bad sound caught by zmagic" << llendl; @@ -616,7 +610,8 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) llwarns << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << llendl; mCurrentDecodep->flushBadFile(); LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID()); - adp->setHasValidData(FALSE); + adp->setHasValidData(false); + adp->setHasCompletedDecode(true); mCurrentDecodep = NULL; done = TRUE; } @@ -631,11 +626,16 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) if (mCurrentDecodep->finishDecode()) { // We finished! - if (mCurrentDecodep->isValid() && mCurrentDecodep->isDone()) + LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID()); + if (!adp) { - LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID()); - adp->setHasDecodedData(TRUE); - adp->setHasValidData(TRUE); + llwarns << "Missing LLAudioData for decode of " << mCurrentDecodep->getUUID() << llendl; + } + else if (mCurrentDecodep->isValid() && mCurrentDecodep->isDone()) + { + adp->setHasCompletedDecode(true); + adp->setHasDecodedData(true); + adp->setHasValidData(true); // At this point, we could see if anyone needs this sound immediately, but // I'm not sure that there's a reason to - we need to poll all of the playing @@ -644,7 +644,8 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs) } else { - llinfos << "Vorbis decode failed!!!" << llendl; + adp->setHasCompletedDecode(true); + llinfos << "Vorbis decode failed for " << mCurrentDecodep->getUUID() << llendl; } mCurrentDecodep = NULL; } @@ -712,15 +713,18 @@ BOOL LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid) if (gAudiop->hasDecodedFile(uuid)) { // Already have a decoded version, don't need to decode it. + //llinfos << "addDecodeRequest for " << uuid << " has decoded file already" << llendl; return TRUE; } if (gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND)) { // Just put it on the decode queue. + //llinfos << "addDecodeRequest for " << uuid << " has local asset file already" << llendl; mImpl->mDecodeQueue.push(uuid); return TRUE; } + //llinfos << "addDecodeRequest for " << uuid << " no file available" << llendl; return FALSE; } diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index d696020bb..7c3f3e315 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -1275,10 +1275,11 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E // Need to mark data as bad to avoid constant rerequests. LLAudioData *adp = gAudiop->getAudioData(uuid); if (adp) - { + { // Make sure everything is cleared adp->setHasValidData(false); adp->setHasLocalData(false); adp->setHasDecodedData(false); + adp->setHasCompletedDecode(true); } } else @@ -1291,9 +1292,10 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E } else { + // llinfos << "Got asset callback with good audio data for " << uuid << ", making decode request" << llendl; adp->setHasValidData(true); - adp->setHasLocalData(true); - gAudioDecodeMgrp->addDecodeRequest(uuid); + adp->setHasLocalData(true); + gAudioDecodeMgrp->addDecodeRequest(uuid); } } gAudiop->mCurrentTransfer = LLUUID::null; @@ -1380,16 +1382,18 @@ void LLAudioSource::update() if (!getCurrentBuffer()) { - if (getCurrentData()) + LLAudioData *adp = getCurrentData(); + if (adp) { // Hack - try and load the sound. Will do this as a callback // on decode later. - if (getCurrentData()->load() && getCurrentData()->getBuffer()) + if (adp->load() && adp->getBuffer()) { - play(getCurrentData()->getID()); + play(adp->getID()); } - else + else if (adp->hasCompletedDecode()) // Only mark corrupted after decode is done { + llwarns << "Marking LLAudioSource corrupted for " << adp->getID() << llendl; mCorrupted = true ; } } @@ -1812,6 +1816,7 @@ LLAudioData::LLAudioData(const LLUUID &uuid) : mBufferp(NULL), mHasLocalData(false), mHasDecodedData(false), + mHasCompletedDecode(false), mHasValidData(true) { if (uuid.isNull()) @@ -1823,12 +1828,13 @@ LLAudioData::LLAudioData(const LLUUID &uuid) : if (gAudiop && gAudiop->hasDecodedFile(uuid)) { // Already have a decoded version, don't need to decode it. - mHasLocalData = true; - mHasDecodedData = true; + setHasLocalData(true); + setHasDecodedData(true); + setHasCompletedDecode(true); } else if (gAssetStorage && gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND)) { - mHasLocalData = true; + setHasLocalData(true); } } diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index 254a1ee1f..c80b71688 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -408,10 +408,12 @@ public: bool hasLocalData() const { return mHasLocalData; } bool hasDecodedData() const { return mHasDecodedData; } + bool hasCompletedDecode() const { return mHasCompletedDecode; } bool hasValidData() const { return mHasValidData; } void setHasLocalData(const bool hld) { mHasLocalData = hld; } void setHasDecodedData(const bool hdd) { mHasDecodedData = hdd; } + void setHasCompletedDecode(const bool hcd) { mHasCompletedDecode = hcd; } void setHasValidData(const bool hvd) { mHasValidData = hvd; } friend class LLAudioEngine; // Severe laziness, bad. @@ -419,9 +421,10 @@ public: protected: LLUUID mID; LLAudioBuffer *mBufferp; // If this data is being used by the audio system, a pointer to the buffer will be set here. - bool mHasLocalData; - bool mHasDecodedData; - bool mHasValidData; + bool mHasLocalData; // Set true if the sound asset file is available locally + bool mHasDecodedData; // Set true if the sound file has been decoded + bool mHasCompletedDecode; // Set true when the sound is decoded + bool mHasValidData; // Set false if decoding failed, meaning the sound asset is bad }; diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp index a9592e1cd..2b2bd19d5 100644 --- a/indra/llaudio/llaudioengine_fmodex.cpp +++ b/indra/llaudio/llaudioengine_fmodex.cpp @@ -105,10 +105,6 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) U32 version; FMOD_RESULT result; - int numdrivers; - FMOD_SPEAKERMODE speakermode; - FMOD_CAPS caps; - char name[256]; LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() initializing FMOD" << LL_ENDL; @@ -124,11 +120,16 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) if (version < FMOD_VERSION) { - LL_WARNS("AppInit") << "Error : You are using the wrong FMOD version (" << version - << ")! You should be using FMOD " << FMOD_VERSION << LL_ENDL; + LL_WARNS("AppInit") << "Error : You are using the wrong FMOD Ex version (" << version + << ")! You should be using FMOD Ex" << FMOD_VERSION << LL_ENDL; } #if LL_WINDOWS + int numdrivers; + FMOD_SPEAKERMODE speakermode; + FMOD_CAPS caps; + char name[256]; + //Is this block applicable to linux? { result = mSystem->getNumDrivers(&numdrivers); @@ -173,7 +174,7 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) #endif //LL_WINDOWS // In this case, all sounds, PLUS wind and stream will be software. - result = mSystem->setSoftwareChannels(num_channels+2); + result = mSystem->setSoftwareChannels(num_channels + 2); Check_FMOD_Error(result,"FMOD::System::setSoftwareChannels"); U32 fmod_flags = FMOD_INIT_NORMAL; @@ -181,73 +182,67 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) fmod_flags |= FMOD_INIT_ENABLE_PROFILE; #if LL_LINUX - // If we don't set an output method, Linux FMOD always - // decides on OSS and fails otherwise. So we'll manually - // try ESD, then OSS, then ALSA. - // Why this order? See SL-13250, but in short, OSS emulated - // on top of ALSA is ironically more reliable than raw ALSA. - // Ack, and ESD has more reliable failure modes - but has worse - // latency - than all of them, so wins for now. bool audio_ok = false; if (!audio_ok) { - if (NULL == getenv("LL_BAD_FMODEX_ESD")) /*Flawfinder: ignore*/ + if (NULL == getenv("LL_BAD_FMOD_PULSEAUDIO")) /*Flawfinder: ignore*/ { - LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL; - if(mSystem->SetOutput(FMOD_OUTPUTTYPE_ESD) == FMOD_OK && - (result = mSystem->init(num_channels, fmod_flags, 0)) == FMOD_OK) + LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL; + if(mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK && + (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) { - LL_DEBUGS("AppInit") << "ESD audio output initialized OKAY" << LL_ENDL; + LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL; audio_ok = true; } else { - Check_FMOD_Error(result, "ESD audio output FAILED to initialize"); + Check_FMOD_Error(result, "PulseAudio audio output FAILED to initialize"); } } else { - LL_DEBUGS("AppInit") << "ESD audio output SKIPPED" << LL_ENDL; + LL_DEBUGS("AppInit") << "PulseAudio audio output SKIPPED" << LL_ENDL; } } if (!audio_ok) { - if (NULL == getenv("LL_BAD_FMODEX_OSS")) /*Flawfinder: ignore*/ + if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/ { - LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL; - if(mSystem->SetOutput(FMOD_OUTPUTTYPE_OSS) == FMOD_OK && - (result = mSystem->init(num_channels, fmod_flags, 0)) == FMOD_OK) + LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; + if(mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK && + (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) { - LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; + LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; audio_ok = true; } else { - Check_FMOD_Error(result, "OSS audio output FAILED to initialize" << LL_ENDL; + Check_FMOD_Error(result, "ALSA audio output FAILED to initialize"); } } else { - LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; + LL_DEBUGS("AppInit") << "ALSA audio output SKIPPED" << LL_ENDL; } } if (!audio_ok) { - if (NULL == getenv("LL_BAD_FMODEX_ALSA")) /*Flawfinder: ignore*/ + if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/ { - LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; - if(mSystem->SetOutput(FMOD_OUTPUTTYPE_ALSA) && - (result = mSystem->init(num_channels, fmod_flags, 0)) == FMOD_OK) + LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL; + if(mSystem->setOutput(FMOD_OUTPUTTYPE_OSS) == FMOD_OK && + (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) { - LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; + LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; audio_ok = true; } else { - Check_FMOD_Error(result, "ALSA audio output FAILED to initialize"); + Check_FMOD_Error(result, "OSS audio output FAILED to initialize"); } - } else + } + else { LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; } @@ -258,25 +253,20 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) return false; } - // On Linux, FMOD causes a SIGPIPE for some netstream error - // conditions (an FMOD bug); ignore SIGPIPE so it doesn't crash us. - // NOW FIXED in FMOD 3.x since 2006-10-01. - //signal(SIGPIPE, SIG_IGN); - // We're interested in logging which output method we // ended up with, for QA purposes. FMOD_OUTPUTTYPE output_type; - mSystem->getOutput(output_type); + mSystem->getOutput(&output_type); switch (output_type) { - case FSOUND_OUTPUT_NOSOUND: - LL_DEBUGS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; - case FSOUND_OUTPUT_OSS: - LL_DEBUGS("AppInit") << "Audio output: OSS" << LL_ENDL; break; - case FSOUND_OUTPUT_ESD: - LL_DEBUGS("AppInit") << "Audio output: ESD" << LL_ENDL; break; - case FSOUND_OUTPUT_ALSA: - LL_DEBUGS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_NOSOUND: + LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_PULSEAUDIO: + LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_ALSA: + LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_OSS: + LL_INFOS("AppInit") << "Audio output: OSS" << LL_ENDL; break; default: LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; }; @@ -295,9 +285,9 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) /* ... and re-init. */ - result = mSystem->init(100, FMOD_INIT_NORMAL, 0); + result = mSystem->init( num_channels + 2, fmod_flags, 0); } - if(Check_FMOD_Error(result, "Error initializing FMOD")) + if(Check_FMOD_Error(result, "Error initializing FMOD Ex")) return false; #endif @@ -305,7 +295,7 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) if (!getStreamingAudioImpl()) // no existing implementation added setStreamingAudioImpl(new LLStreamingAudio_FMODEX(mSystem)); - LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() FMOD initialized correctly" << LL_ENDL; + LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init() FMOD Ex initialized correctly" << LL_ENDL; mInited = true; @@ -321,10 +311,10 @@ std::string LLAudioEngine_FMODEX::getDriverName(bool verbose) U32 version; if(!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion")) { - return llformat("FMOD version %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF); + return llformat("FMOD Ex %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF); } } - return "FMOD"; + return "FMODEx"; } @@ -342,12 +332,13 @@ void LLAudioEngine_FMODEX::shutdown() { stopInternetStream(); + llinfos << "About to LLAudioEngine::shutdown()" << llendl; LLAudioEngine::shutdown(); - llinfos << "LLAudioEngine_FMODEX::shutdown() closing FMOD" << llendl; + llinfos << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << llendl; mSystem->close(); mSystem->release(); - llinfos << "LLAudioEngine_FMODEX::shutdown() done closing FMOD" << llendl; + llinfos << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << llendl; delete mListenerp; mListenerp = NULL; @@ -374,6 +365,7 @@ bool LLAudioEngine_FMODEX::initWind() FMOD_DSP_DESCRIPTION dspdesc; memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); //Set everything to zero strncpy(dspdesc.name,"Wind Unit", sizeof(dspdesc.name)); //Set name to "Wind Unit" + dspdesc.channels=2; dspdesc.read = &windCallback; //Assign callback. if(Check_FMOD_Error(mSystem->createDSP(&dspdesc, &mWindDSP), "FMOD::createDSP")) return false; diff --git a/indra/llaudio/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp index 8682664b6..d06654ace 100644 --- a/indra/llaudio/llvorbisencode.cpp +++ b/indra/llaudio/llvorbisencode.cpp @@ -89,7 +89,7 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro // ******************************** LLAPRFile infile ; - infile.open(in_fname,LL_APR_RB); + infile.open(in_fname,LL_APR_RB); // ******************************** if (!infile.getFileHandle()) { diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index b4dedad11..9ef121624 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -44,7 +44,7 @@ #include "llapr.h" -using namespace std; +//using namespace std; #define INCHES_TO_METERS 0.02540005f diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index 36e3d99f1..85291530c 100644 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -56,8 +56,7 @@ LLCharacter::LLCharacter() mPreferredPelvisHeight( 0.f ), mSex( SEX_FEMALE ), mAppearanceSerialNum( 0 ), - mSkeletonSerialNum( 0 ), - mInAppearance( false ) + mSkeletonSerialNum( 0 ) { llassert_always(sAllowInstancesChange) ; sInstances.push_back(this); diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index b92805045..5fad36b1c 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -268,10 +268,6 @@ public: ESex getSex() const { return mSex; } void setSex( ESex sex ) { mSex = sex; } - // set appearance flag - void setAppearanceFlag( bool flag ) { mInAppearance = flag; } - bool getAppearanceFlag() { return mInAppearance; } - U32 getAppearanceSerialNum() const { return mAppearanceSerialNum; } void setAppearanceSerialNum( U32 num ) { mAppearanceSerialNum = num; } @@ -293,8 +289,6 @@ protected: U32 mSkeletonSerialNum; LLAnimPauseRequest mPauseRequest; - BOOL mInAppearance; - private: // visual parameter stuff typedef std::map visual_param_index_map_t; diff --git a/indra/llcharacter/llgesture.cpp b/indra/llcharacter/llgesture.cpp index 83e4e35b0..c23694639 100644 --- a/indra/llcharacter/llgesture.cpp +++ b/indra/llcharacter/llgesture.cpp @@ -1,31 +1,25 @@ /** * @file llgesture.cpp * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llcharacter/llgesture.h b/indra/llcharacter/llgesture.h index d394ab763..66b618c47 100644 --- a/indra/llcharacter/llgesture.h +++ b/indra/llcharacter/llgesture.h @@ -3,31 +3,25 @@ * @brief A gesture is a combination of a triggering chat phrase or * key, a sound, an animation, and a chat string. * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llcharacter/llheadrotmotion.cpp b/indra/llcharacter/llheadrotmotion.cpp index 80274e886..9d12ee98d 100644 --- a/indra/llcharacter/llheadrotmotion.cpp +++ b/indra/llcharacter/llheadrotmotion.cpp @@ -510,20 +510,6 @@ BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask) vergence_quat.transQuat(); right_eye_rot = vergence_quat * eye_jitter_rot * right_eye_rot; - //if in appearance, set the eyes straight forward - if(mCharacter->getAppearanceFlag()) // no idea why this variable is reversed - { - LLVector3 forward(1.f, 0.0, 0.0); - LLVector3 left; - LLVector3 up; - left.setVec(forward % forward); - up.setVec(forward % left); - target_eye_rot = LLQuaternion(forward, left, up); - mLeftEyeState->setRotation( target_eye_rot ); - mRightEyeState->setRotation( target_eye_rot ); - return TRUE; - } - mLeftEyeState->setRotation( left_eye_rot ); mRightEyeState->setRotation( right_eye_rot ); diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index 144cbe747..6f769ab7e 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -480,7 +480,7 @@ LLPointer& LLKeyframeMotion::getJointState(U32 index) } //----------------------------------------------------------------------------- -// getJoin() +// getJoint() //----------------------------------------------------------------------------- LLJoint* LLKeyframeMotion::getJoint(U32 index) { diff --git a/indra/llcharacter/llmultigesture.cpp b/indra/llcharacter/llmultigesture.cpp index 7fe21dbc9..e7e6575de 100644 --- a/indra/llcharacter/llmultigesture.cpp +++ b/indra/llcharacter/llmultigesture.cpp @@ -2,31 +2,25 @@ * @file llmultigesture.cpp * @brief Gestures that are asset-based and can have multiple steps. * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -50,6 +44,7 @@ const S32 GESTURE_VERSION = 2; LLMultiGesture::LLMultiGesture() : mKey(), mMask(), + mName(), mTrigger(), mReplaceText(), mSteps(), @@ -292,20 +287,27 @@ BOOL LLGestureStepAnimation::deserialize(LLDataPacker& dp) dp.unpackU32(mFlags, "flags"); return TRUE; } - -std::string LLGestureStepAnimation::getLabel() const +// *NOTE: result is translated in LLPreviewGesture::getLabel() +std::vector LLGestureStepAnimation::getLabel() const { - std::string label; + std::vector strings; + +// std::string label; if (mFlags & ANIM_FLAG_STOP) { - label = "Stop Animation: "; + strings.push_back( "AnimFlagStop"); + +// label = "Stop Animation: "; } else { - label = "Start Animation: "; + strings.push_back( "AnimFlagStart"); + +// label = "Start Animation: "; } - label += mAnimName; - return label; + strings.push_back( mAnimName); +// label += mAnimName; + return strings; } void LLGestureStepAnimation::dump() @@ -359,12 +361,15 @@ BOOL LLGestureStepSound::deserialize(LLDataPacker& dp) dp.unpackU32(mFlags, "flags"); return TRUE; } - -std::string LLGestureStepSound::getLabel() const +// *NOTE: result is translated in LLPreviewGesture::getLabel() +std::vector LLGestureStepSound::getLabel() const { - std::string label("Sound: "); - label += mSoundName; - return label; + std::vector strings; + strings.push_back( "Sound"); + strings.push_back( mSoundName); +// std::string label("Sound: "); +// label += mSoundName; + return strings; } void LLGestureStepSound::dump() @@ -414,12 +419,13 @@ BOOL LLGestureStepChat::deserialize(LLDataPacker& dp) dp.unpackU32(mFlags, "flags"); return TRUE; } - -std::string LLGestureStepChat::getLabel() const +// *NOTE: result is translated in LLPreviewGesture::getLabel() +std::vector LLGestureStepChat::getLabel() const { - std::string label("Chat: "); - label += mChatText; - return label; + std::vector strings; + strings.push_back("Chat"); + strings.push_back(mChatText); + return strings; } void LLGestureStepChat::dump() @@ -467,22 +473,31 @@ BOOL LLGestureStepWait::deserialize(LLDataPacker& dp) dp.unpackU32(mFlags, "flags"); return TRUE; } - -std::string LLGestureStepWait::getLabel() const +// *NOTE: result is translated in LLPreviewGesture::getLabel() +std::vector LLGestureStepWait::getLabel() const { - std::string label("--- Wait: "); + std::vector strings; + strings.push_back( "Wait" ); + +// std::string label("--- Wait: "); if (mFlags & WAIT_FLAG_TIME) { char buffer[64]; /* Flawfinder: ignore */ snprintf(buffer, sizeof(buffer), "%.1f seconds", (double)mWaitSeconds); /* Flawfinder: ignore */ - label += buffer; + strings.push_back(buffer); +// label += buffer; } else if (mFlags & WAIT_FLAG_ALL_ANIM) { - label += "until animations are done"; + strings.push_back("until animations are done"); + // label += "until animations are done"; + } + else + { + strings.push_back(""); } - return label; + return strings; } diff --git a/indra/llcharacter/llmultigesture.h b/indra/llcharacter/llmultigesture.h index eb15f600c..0c027b31b 100644 --- a/indra/llcharacter/llmultigesture.h +++ b/indra/llcharacter/llmultigesture.h @@ -70,6 +70,10 @@ public: KEY mKey; MASK mMask; + // This name can be empty if the inventory item is not around and + // the gesture manager has not yet set the name + std::string mName; + // String, like "/foo" or "hello" that makes it play std::string mTrigger; @@ -130,7 +134,7 @@ public: virtual EStepType getType() = 0; // Return a user-readable label for this step - virtual std::string getLabel() const = 0; + virtual std::vector getLabel() const = 0; virtual S32 getMaxSerialSize() const = 0; virtual BOOL serialize(LLDataPacker& dp) const = 0; @@ -152,7 +156,7 @@ public: virtual EStepType getType() { return STEP_ANIMATION; } - virtual std::string getLabel() const; + virtual std::vector getLabel() const; virtual S32 getMaxSerialSize() const; virtual BOOL serialize(LLDataPacker& dp) const; @@ -175,7 +179,7 @@ public: virtual EStepType getType() { return STEP_SOUND; } - virtual std::string getLabel() const; + virtual std::vector getLabel() const; virtual S32 getMaxSerialSize() const; virtual BOOL serialize(LLDataPacker& dp) const; @@ -198,7 +202,7 @@ public: virtual EStepType getType() { return STEP_CHAT; } - virtual std::string getLabel() const; + virtual std::vector getLabel() const; virtual S32 getMaxSerialSize() const; virtual BOOL serialize(LLDataPacker& dp) const; @@ -223,7 +227,7 @@ public: virtual EStepType getType() { return STEP_WAIT; } - virtual std::string getLabel() const; + virtual std::vector getLabel() const; virtual S32 getMaxSerialSize() const; virtual BOOL serialize(LLDataPacker& dp) const; diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp index 122406e20..809b312ab 100644 --- a/indra/llcharacter/llvisualparam.cpp +++ b/indra/llcharacter/llvisualparam.cpp @@ -2,31 +2,25 @@ * @file llvisualparam.cpp * @brief Implementation of LLPolyMesh class. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h index 63b9d6893..a70efa9dd 100644 --- a/indra/llcharacter/llvisualparam.h +++ b/indra/llcharacter/llvisualparam.h @@ -2,31 +2,25 @@ * @file llvisualparam.h * @brief Implementation of LLPolyMesh class. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 2ff8856ec..29feeebc4 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -121,6 +121,7 @@ set(llcommon_HEADER_FILES llaprpool.h llassettype.h llassoclist.h + llatomic.h llavatarconstants.h llbase32.h llbase64.h diff --git a/indra/llcommon/aithreadsafe.h b/indra/llcommon/aithreadsafe.h index 0cff3b77a..b7d0045cb 100644 --- a/indra/llcommon/aithreadsafe.h +++ b/indra/llcommon/aithreadsafe.h @@ -26,8 +26,65 @@ * * 31/03/2010 * Initial version, written by Aleric Inglewood @ SL + * + * 14/03/2012 + * Added AIThreadSafeSingleThread and friends. + * Added AIAccessConst (and derived AIAccess from it) to allow read + * access to a const AIThreadSafeSimple. */ +// This file defines wrapper template classes for arbitrary types T +// adding locking to the instance and shielding it from access +// without first being locked. +// +// Locking and getting access works by creating a temporary (local) +// access object that takes the wrapper class as argument. Creating +// the access object obtains the lock, while destructing it releases +// the lock. +// +// There are three types of wrapper classes: +// AIThreadSafe, AIThreadSafeSimple and AIThreadSafeSingleThread. +// +// AIThreadSafe is for use with the access classes: +// AIReadAccessConst, AIReadAccess and AIWriteAccess. +// +// AIThreadSafeSimple is for use with the access classes: +// AIAccessConst and AIAccess. +// +// AIThreadSafeSingleThread is for use with the access classes: +// AISTAccessConst and AISTAccess. +// +// AIReadAccessConst provides read access to a const AIThreadSafe. +// AIReadAccess provides read access to a non-const AIThreadSafe. +// AIWriteAccess provides read/write access to a non-const AIThreadSafe. +// +// AIAccessConst provides read access to a const AIThreadSafeSimple. +// AIAccess provides read/write access to a non-const AIThreadSafeSimple. +// +// AISTAccessConst provides read access to a const AIThreadSafeSingleThread. +// AISTAccess provides read/write access to a non-const AIThreadSafeSingleThread. +// +// Thus, AIThreadSafe is to protect objects with a read/write lock, +// AIThreadSafeSimple is to protect objects with a single mutex, +// and AIThreadSafeSingleThread doesn't do any locking but makes sure +// (in Debug mode) that the wrapped object is only accessed by one thread. +// +// Each wrapper class allows its wrapped object to be constructed +// with arbitrary parameters by using operator new with placement; +// for example, to instantiate a class Foo with read/write locking: +// +// AIThreadSafe foo(new (foo.memory()) Foo(param1, param2, ...)); +// +// Each wrapper class has a derived class that end on 'DC' (which +// stand for Default Constructed): AIThreadSafeDC, AIThreadSafeSimpleDC +// and AIThreadSafeSingleThreadDC. The default constructors of those +// wrapper classes cause the wrapped instance to be default constructed +// as well. They also provide a general one-parameter constructor. +// For example: +// +// AIThreadSafeDC foo; // Default constructed Foo. +// AIThreadSafeDC foo(3.4); // Foo with one constructor parameter. +// #ifndef AITHREADSAFE_H #define AITHREADSAFE_H @@ -49,15 +106,10 @@ template struct AIReadAccessConst; template struct AIReadAccess; template struct AIWriteAccess; +template struct AIAccessConst; template struct AIAccess; - -#if LL_WINDOWS -template class AIThreadSafeBits; -template -struct AIThreadSafeWindowsHack { - AIThreadSafeWindowsHack(AIThreadSafeBits& var, T* object); -}; -#endif +template struct AISTAccessConst; +template struct AISTAccess; template class AIThreadSafeBits @@ -80,10 +132,15 @@ public: // Only for use by AITHREADSAFE, see below. void* memory() const { return const_cast(&mMemory[0]); } + // Cast a T* back to AIThreadSafeBits. This is the inverse of memory(). + template + static AIThreadSafeBits* wrapper_cast(T2* ptr) + { return reinterpret_cast*>(reinterpret_cast(ptr) - offsetof(AIThreadSafeBits, mMemory[0])); } + template + static AIThreadSafeBits const* wrapper_cast(T2 const* ptr) + { return reinterpret_cast const*>(reinterpret_cast(ptr) - offsetof(AIThreadSafeBits, mMemory[0])); } + protected: -#if LL_WINDOWS - template friend struct AIThreadSafeWindowsHack; -#endif // Accessors. T const* ptr() const { return reinterpret_cast(mMemory); } T* ptr() { return reinterpret_cast(mMemory); } @@ -185,6 +242,14 @@ public: llassert(object == AIThreadSafeBits::ptr()); #endif } + +#if LL_DEBUG + // Can only be locked when there still exists an AIAccess object that + // references this object and will access it upon destruction. + // If the assertion fails, make sure that such AIAccess object is + // destructed before the deletion of this object. + ~AIThreadSafe() { llassert(!mRWLock.isLocked()); } +#endif }; /** @@ -194,48 +259,39 @@ public: * * * Foo foo(x, y); - * static Bar bar; + * static Bar bar(0.1, true); * * * One can instantiate a thread-safe instance with * * * AITHREADSAFE(Foo, foo, (x, y)); - * static AITHREADSAFE(Bar, bar, ); + * static AITHREADSAFE(Bar, bar, (0.1, true)); * * * Note: This macro does not allow to allocate such object on the heap. * If that is needed, have a look at AIThreadSafeDC. */ -#if LL_WINDOWS -template -AIThreadSafeWindowsHack::AIThreadSafeWindowsHack(AIThreadSafeBits& var, T* object) -{ - llassert(object == var.ptr()); -} -#define AITHREADSAFE(type, var, paramlist) \ - AIThreadSafe var(NULL); \ - AIThreadSafeWindowsHack dummy_##var(var, new (var.memory()) type paramlist) -#else #define AITHREADSAFE(type, var, paramlist) AIThreadSafe var(new (var.memory()) type paramlist) -#endif /** * @brief A wrapper class for objects that need to be accessed by more than one thread. * * This class is the same as an AIThreadSafe wrapper, except that it can only - * be used for default constructed objects. + * be used for default constructed objects, or constructed with one parameter. * * For example, instead of * * * Foo foo; + * Bar bar(3); * * * One would use * * * AIThreadSafeDC foo; + * AIThreadSafeDC bar(3); * * * The advantage over AITHREADSAFE is that this object can be allocated with @@ -253,6 +309,8 @@ class AIThreadSafeDC : public AIThreadSafe public: // Construct a wrapper around a default constructed object. AIThreadSafeDC(void) { new (AIThreadSafe::ptr()) T; } + // Allow an arbitrary parameter to be passed for construction. + template AIThreadSafeDC(T2 const& val) { new (AIThreadSafe::ptr()) T(val); } }; /** @@ -390,6 +448,7 @@ struct AIWriteAccess : public AIReadAccess * * AIAccess foo_w(foo); * // Use foo_w-> for read and write access. + * * * See also AIThreadSafe */ @@ -398,6 +457,7 @@ class AIThreadSafeSimple : public AIThreadSafeBits { protected: // Only this one may access the object (through ptr()). + friend struct AIAccessConst; friend struct AIAccess; // Locking control. @@ -411,6 +471,14 @@ protected: public: // Only for use by AITHREADSAFESIMPLE, see below. AIThreadSafeSimple(T* object) { llassert(object == AIThreadSafeBits::ptr()); } + +#if LL_DEBUG + // Can only be locked when there still exists an AIAccess object that + // references this object and will access it upon destruction. + // If the assertion fails, make sure that such AIAccess object is + // destructed before the deletion of this object. + ~AIThreadSafeSimple() { llassert(!mMutex.isLocked()); } +#endif }; /** @@ -420,14 +488,14 @@ public: * * * Foo foo(x, y); - * static Bar bar; + * static Bar bar(0.1, true); * * * One can instantiate a thread-safe instance with * * * AITHREADSAFESIMPLE(Foo, foo, (x, y)); - * static AITHREADSAFESIMPLE(Bar, bar, ); + * static AITHREADSAFESIMPLE(Bar, bar, (0.1, true)); * * * Note: This macro does not allow to allocate such object on the heap. @@ -439,18 +507,20 @@ public: * @brief A wrapper class for objects that need to be accessed by more than one thread. * * This class is the same as an AIThreadSafeSimple wrapper, except that it can only - * be used for default constructed objects. + * be used for default constructed objects, or constructed with one parameter. * * For example, instead of * * * Foo foo; + * Bar bar(0.1); * * * One would use * * * AIThreadSafeSimpleDC foo; + * AIThreadSafeSimpleDC bar(0.1); * * * The advantage over AITHREADSAFESIMPLE is that this object can be allocated with @@ -468,10 +538,12 @@ class AIThreadSafeSimpleDC : public AIThreadSafeSimple public: // Construct a wrapper around a default constructed object. AIThreadSafeSimpleDC(void) { new (AIThreadSafeSimple::ptr()) T; } + // Allow an arbitrary parameter to be passed for construction. + template AIThreadSafeSimpleDC(T2 const& val) { new (AIThreadSafeSimple::ptr()) T(val); } protected: // For use by AIThreadSafeSimpleDCRootPool - AIThreadSafeSimpleDC(LLAPRPool& parent) : AIThreadSafeSimple(parent) { new (AIThreadSafeSimple::ptr()) T; } + AIThreadSafeSimpleDC(LLAPRRootPool& parent) : AIThreadSafeSimple(parent) { new (AIThreadSafeSimple::ptr()) T; } }; // Helper class for AIThreadSafeSimpleDCRootPool to assure initialization of @@ -493,7 +565,7 @@ private: * for the internally used mutexes and condition, instead of using the current threads * root pool. The advantage of this is that it can be used for objects that need to * be accessed from the destructors of global objects (after main). The disadvantage - * is that it's less efficient to use your own root pool, therefore it's use should be + * is that it's less efficient to use your own root pool, therefore its use should be * restricted to those cases where it is absolutely necessary. */ template @@ -509,13 +581,13 @@ public: }; /** - * @brief Write lock object and provide read/write access. + * @brief Write lock object and provide read access. */ template -struct AIAccess +struct AIAccessConst { - //! Construct a AIAccess from a non-constant AIThreadSafeSimple. - AIAccess(AIThreadSafeSimple& wrapper) : mWrapper(wrapper) + //! Construct a AIAccessConst from a constant AIThreadSafeSimple. + AIAccessConst(AIThreadSafeSimple const& wrapper) : mWrapper(const_cast&>(wrapper)) #if AI_NEED_ACCESS_CC , mIsCopyConstructed(false) #endif @@ -524,12 +596,12 @@ struct AIAccess } //! Access the underlaying object for (read and) write access. - T* operator->() const { return this->mWrapper.ptr(); } + T const* operator->() const { return this->mWrapper.ptr(); } //! Access the underlaying object for (read and) write access. - T& operator*() const { return *this->mWrapper.ptr(); } + T const& operator*() const { return *this->mWrapper.ptr(); } - ~AIAccess() + ~AIAccessConst() { #if AI_NEED_ACCESS_CC if (mIsCopyConstructed) return; @@ -538,17 +610,229 @@ struct AIAccess } protected: - AIThreadSafeSimple& mWrapper; //!< Reference to the object that we provide access to. + AIThreadSafeSimple& mWrapper; //!< Reference to the object that we provide access to. #if AI_NEED_ACCESS_CC bool mIsCopyConstructed; public: - AIAccess(AIAccess const& orig) : mWrapper(orig.mWrapper), mIsCopyConstructed(true) { } + AIAccessConst(AIAccessConst const& orig) : mWrapper(orig.mWrapper), mIsCopyConstructed(true) { } #else private: // Disallow copy constructing directly. - AIAccess(AIAccess const&); + AIAccessConst(AIAccessConst const&); #endif }; +/** + * @brief Write lock object and provide read/write access. + */ +template +struct AIAccess : public AIAccessConst +{ + //! Construct a AIAccess from a non-constant AIThreadSafeSimple. + AIAccess(AIThreadSafeSimple& wrapper) : AIAccessConst(wrapper) { } + + //! Access the underlaying object for (read and) write access. + T* operator->() const { return this->mWrapper.ptr(); } + + //! Access the underlaying object for (read and) write access. + T& operator*() const { return *this->mWrapper.ptr(); } +}; + +/** + * @brief A wrapper class for objects that should only be accessed by a single thread. + * + * Use AITHREADSAFESINGLETHREAD to define instances of any type, and use AISTAccess + * to get access to the instance. + * + * For example, + * + * + * class Foo { public: Foo(int, int); }; + * + * AITHREADSAFESINGLETHREAD(Foo, foo, (2, 3)); + * + * AISTAccess foo_w(foo); + * // Use foo_w-> for read and write access. + * + */ +template +class AIThreadSafeSingleThread : public AIThreadSafeBits +{ +protected: + // Only these one may access the object (through ptr()). + friend struct AISTAccessConst; + friend struct AISTAccess; + + // For use by AIThreadSafeSingleThreadDC. + AIThreadSafeSingleThread(void) +#ifdef LL_DEBUG + : mAccessed(false) +#endif + { } + +#ifdef LL_DEBUG + mutable bool mAccessed; + mutable apr_os_thread_t mTheadID; + + void accessed(void) const + { + if (!mAccessed) + { + mAccessed = true; + mTheadID = apr_os_thread_current(); + } + else + { + llassert_always(apr_os_thread_equal(mTheadID, apr_os_thread_current())); + } + } +#endif + +public: + // Only for use by AITHREADSAFESINGLETHREAD, see below. + AIThreadSafeSingleThread(T* object) +#ifdef LL_DEBUG + : mAccessed(false) +#endif + { + llassert(object == AIThreadSafeBits::ptr()); + } + +private: + // Disallow copying or assignments. + AIThreadSafeSingleThread(AIThreadSafeSingleThread const&); + void operator=(AIThreadSafeSingleThread const&); +}; + +/** + * @brief A wrapper class for objects that should only be accessed by a single thread. + * + * This class is the same as an AIThreadSafeSingleThread wrapper, except that it can only + * be used for default constructed objects, or constructed with one parameter. + * + * For example, instead of + * + * + * Foo foo; + * Bar bar(0.1); + * + * + * One would use + * + * + * AIThreadSafeSingleThreadDC foo; + * AIThreadSafeSingleThreadDC bar(0.1); + * + * + * The advantage over AITHREADSAFESINGLETHREAD is that this object can be allocated with + * new on the heap. For example: + * + * + * AIThreadSafeSingleThreadDC* ptr = new AIThreadSafeSingleThreadDC; + * + * + * which is not possible with AITHREADSAFESINGLETHREAD. + * + * This class is primarily intended to test if some (member) variable needs locking, + * during development (in debug mode), and is therefore more flexible in that it + * automatically converts to the underlying type, can be assigned to and can be + * written to an ostream, as if it wasn't wrapped at all. This is to reduce the + * impact on the source code. + */ +template +class AIThreadSafeSingleThreadDC : public AIThreadSafeSingleThread +{ +public: + // Construct a wrapper around a default constructed object. + AIThreadSafeSingleThreadDC(void) { new (AIThreadSafeSingleThread::ptr()) T; } + // Allow an arbitrary parameter to be passed for construction. + template AIThreadSafeSingleThreadDC(T2 const& val) { new (AIThreadSafeSingleThread::ptr()) T(val); } + + // Allow assigning with T. + AIThreadSafeSingleThreadDC& operator=(T const& val) { AIThreadSafeSingleThread::accessed(); *AIThreadSafeSingleThread::ptr() = val; return *this; } + // Allow writing to an ostream. + friend std::ostream& operator<<(std::ostream& os, AIThreadSafeSingleThreadDC const& wrapped_val) { wrapped_val.accessed(); return os << *wrapped_val.ptr(); } + + // Automatic conversion to T. + operator T&(void) { AIThreadSafeSingleThread::accessed(); return *AIThreadSafeSingleThread::ptr(); } + operator T const&(void) const { AIThreadSafeSingleThread::accessed(); return *AIThreadSafeSingleThread::ptr(); } +}; + +/** + * @brief Instantiate a static, global or local object of a given type wrapped in AIThreadSafeSingleThread, using an arbitrary constructor. + * + * For example, instead of doing + * + * + * Foo foo(x, y); + * static Bar bar; + * + * + * One can instantiate a thread-safe instance with + * + * + * AITHREADSAFESINGLETHREAD(Foo, foo, (x, y)); + * static AITHREADSAFESINGLETHREAD(Bar, bar, ); + * + * + * Note: This macro does not allow to allocate such object on the heap. + * If that is needed, have a look at AIThreadSafeSingleThreadDC. + */ +#define AITHREADSAFESINGLETHREAD(type, var, paramlist) AIThreadSafeSingleThread var(new (var.memory()) type paramlist) + +/** + * @brief Access single threaded object for read access. + */ +template +struct AISTAccessConst +{ + //! Construct a AISTAccessConst from a constant AIThreadSafeSingleThread. + AISTAccessConst(AIThreadSafeSingleThread const& wrapper) : mWrapper(const_cast&>(wrapper)) + { +#if LL_DEBUG + wrapper.accessed(); +#endif + } + + //! Access the underlaying object for read access. + T const* operator->() const { return this->mWrapper.ptr(); } + + //! Access the underlaying object for read write access. + T const& operator*() const { return *this->mWrapper.ptr(); } + +protected: + AIThreadSafeSingleThread& mWrapper; //!< Reference to the object that we provide access to. + +#if AI_NEED_ACCESS_CC +public: + AISTAccessConst(AISTAccessConst const& orig) : mWrapper(orig.mWrapper) { } +#else +private: + // Disallow copy constructing directly. + AISTAccessConst(AISTAccessConst const&); +#endif +}; + +/** + * @brief Access single threaded object for read/write access. + */ +template +struct AISTAccess : public AISTAccessConst +{ + //! Construct a AISTAccess from a non-constant AIThreadSafeSingleThread. + AISTAccess(AIThreadSafeSingleThread& wrapper) : AISTAccessConst(wrapper) + { +#if LL_DEBUG + wrapper.accessed(); +#endif + } + + //! Access the underlaying object for (read and) write access. + T* operator->() const { return this->mWrapper.ptr(); } + + //! Access the underlaying object for (read and) write access. + T& operator*() const { return *this->mWrapper.ptr(); } +}; + #endif diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 815145ac8..3668be93f 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -375,7 +375,7 @@ const U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13; const U32 MAP_ITEM_TELEHUB = 0x01; const U32 MAP_ITEM_PG_EVENT = 0x02; const U32 MAP_ITEM_MATURE_EVENT = 0x03; -const U32 MAP_ITEM_POPULAR = 0x04; +//const U32 MAP_ITEM_POPULAR = 0x04; // No longer supported, 2009-03-02 KLW //const U32 MAP_ITEM_AGENT_COUNT = 0x05; const U32 MAP_ITEM_AGENT_LOCATIONS = 0x06; const U32 MAP_ITEM_LAND_FOR_SALE = 0x07; diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 168121c0f..cb2b3c0ca 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -74,7 +74,7 @@ S32 LL_HEARTBEAT_SIGNAL = (SIGRTMAX >= 0) ? (SIGRTMAX-0) : SIGUSR2; // the static application instance LLApp* LLApp::sApplication = NULL; -// Allows the generation of core files for post mortum under gdb +// Allows the generation of core files for post mortem under gdb // and disables crashlogger BOOL LLApp::sDisableCrashlogger = FALSE; @@ -396,6 +396,7 @@ bool LLApp::isQuitting() return (APP_STATUS_QUITTING == sStatus); } +// static bool LLApp::isExiting() { return isQuitting() || isError(); diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index ee7717f12..d16b87cd7 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -88,7 +88,7 @@ bool ll_apr_warn_status(apr_status_t status) void ll_apr_assert_status(apr_status_t status) { - llassert(ll_apr_warn_status(status) == false); + llassert(!ll_apr_warn_status(status)); } //--------------------------------------------------------------------- @@ -146,7 +146,7 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc apr_status_t status; { - apr_pool_t* apr_file_open_pool; + apr_pool_t* apr_file_open_pool; // The use of apr_pool_t is OK here. // This is a temporary variable for a pool that is passed directly to apr_file_open below. if (access_type == short_lived) { @@ -199,7 +199,6 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOO // File I/O S32 LLAPRFile::read(void *buf, S32 nbytes) { - //llassert_always(mFile); (ASC-TUDCC) -HgB if(!mFile) { llwarns << "apr mFile is removed by somebody else. Can not read." << llendl ; @@ -222,7 +221,6 @@ S32 LLAPRFile::read(void *buf, S32 nbytes) S32 LLAPRFile::write(const void *buf, S32 nbytes) { - // llassert_always(mFile); (ASC-TUDCC) -HgB if(!mFile) { llwarns << "apr mFile is removed by somebody else. Can not write." << llendl ; diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index e7c3c53f1..61f3f97c0 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -91,29 +91,8 @@ protected: apr_thread_mutex_t* mMutex; }; -template class LLAtomic32 -{ -public: - LLAtomic32() {}; - LLAtomic32(Type x) {apr_atomic_set32(&mData, apr_uint32_t(x)); }; - ~LLAtomic32() {}; - - operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); } - Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); } - void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); } - void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); } - Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++ - Type operator --(int) { return apr_atomic_dec32(&mData); } // Type-- - -private: - apr_uint32_t mData; -}; - -typedef LLAtomic32 LLAtomicU32; -typedef LLAtomic32 LLAtomicS32; - // File IO convenience functions. -// Returns NULL if the file fails to openm sets *sizep to file size of not NULL +// Returns NULL if the file fails to open, sets *sizep to file size if not NULL // abbreviated flags #define LL_APR_R (APR_READ) // "r" #define LL_APR_W (APR_CREATE|APR_TRUNCATE|APR_WRITE) // "w" @@ -131,7 +110,7 @@ typedef LLAtomic32 LLAtomicS32; // especially do not put some time-costly operations between open() and close(). // otherwise it might lock the APRFilePool. //there are two different apr_pools the APRFile can use: -// 1, a temperary pool passed to an APRFile function, which is used within this function and only once. +// 1, a temporary pool passed to an APRFile function, which is used within this function and only once. // 2, a global pool. // @@ -189,7 +168,7 @@ public: }; /** - * @brief Function which approprately logs error or remains quiet on + * @brief Function which appropriately logs error or remains quiet on * APR_SUCCESS. * @return Returns true if status is an error condition. */ diff --git a/indra/llcommon/llaprpool.cpp b/indra/llcommon/llaprpool.cpp index 03ab406a2..3559ff430 100644 --- a/indra/llcommon/llaprpool.cpp +++ b/indra/llcommon/llaprpool.cpp @@ -1,5 +1,5 @@ /** - * @file LLAPRPool.cpp + * @file llaprpool.cpp * * Copyright (c) 2010, Aleric Inglewood. * diff --git a/indra/llcommon/llaprpool.h b/indra/llcommon/llaprpool.h index aefdaa08b..dc123e942 100644 --- a/indra/llcommon/llaprpool.h +++ b/indra/llcommon/llaprpool.h @@ -1,5 +1,5 @@ /** - * @file LLAPRPool.h + * @file llaprpool.h * @brief Implementation of LLAPRPool. * * Copyright (c) 2010, Aleric Inglewood. @@ -60,9 +60,9 @@ extern void ll_init_apr(); class LL_COMMON_API LLAPRPool { protected: - apr_pool_t* mPool; //!< Pointer to the underlaying pool. NULL if not initialized. + apr_pool_t* mPool; //!< Pointer to the underlaying pool. NULL if not initialized. LLAPRPool* mParent; //!< Pointer to the parent pool, if any. Only valid when mPool is non-zero. - apr_os_thread_t mOwner; //!< The thread that owns this memory pool. Only valid when mPool is non-zero. + apr_os_thread_t mOwner; //!< The thread that owns this memory pool. Only valid when mPool is non-zero. public: //! Construct an uninitialized (destructed) pool. diff --git a/indra/llcommon/llatomic.h b/indra/llcommon/llatomic.h new file mode 100644 index 000000000..3cc5bcf38 --- /dev/null +++ b/indra/llcommon/llatomic.h @@ -0,0 +1,61 @@ +/** + * @file llatomic.h + * @brief Definition of LLAtomic + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * Copyright (c) 2012, Aleric Inglewood + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLATOMIC_H +#define LL_LLATOMIC_H + +#include "apr_atomic.h" + +template class LLAtomic32 +{ +public: + LLAtomic32(void) { } + LLAtomic32(LLAtomic32 const& atom) { apr_uint32_t data = apr_atomic_read32(const_cast(&atom.mData)); apr_atomic_set32(&mData, data); } + LLAtomic32(Type x) { apr_atomic_set32(&mData, static_cast(x)); } + LLAtomic32& operator=(LLAtomic32 const& atom) { apr_uint32_t data = apr_atomic_read32(const_cast(&atom.mData)); apr_atomic_set32(&mData, data); return *this; } + + operator Type() const { apr_uint32_t data = apr_atomic_read32(const_cast(&mData)); return static_cast(data); } + void operator=(Type x) { apr_atomic_set32(&mData, static_cast(x)); } + void operator-=(Type x) { apr_atomic_sub32(&mData, static_cast(x)); } + void operator+=(Type x) { apr_atomic_add32(&mData, static_cast(x)); } + Type operator++(int) { return apr_atomic_inc32(&mData); } // Type++ + bool operator--() { return apr_atomic_dec32(&mData); } // Returns (--Type != 0) + +private: + apr_uint32_t mData; +}; + +typedef LLAtomic32 LLAtomicU32; +typedef LLAtomic32 LLAtomicS32; + +#endif diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp index 5088e94e6..cce8d33b4 100644 --- a/indra/llcommon/llavatarname.cpp +++ b/indra/llcommon/llavatarname.cpp @@ -99,7 +99,7 @@ std::string LLAvatarName::getCompleteName(bool linefeed) const } else { - name = mDisplayName + (linefeed ? "\n(" : "(") + mUsername + ")"; + name = mDisplayName + (linefeed ? "\n(" : " (") + mUsername + ")"; } return name; } diff --git a/indra/llcommon/llbase32.h b/indra/llcommon/llbase32.h index 47cd893d9..0697f7b8e 100644 --- a/indra/llcommon/llbase32.h +++ b/indra/llcommon/llbase32.h @@ -32,7 +32,7 @@ */ #ifndef LLBASE32_H -#define LLBASE32_h +#define LLBASE32_H class LL_COMMON_API LLBase32 { diff --git a/indra/llcommon/llbase64.h b/indra/llcommon/llbase64.h index 15b27a65d..c48fea247 100644 --- a/indra/llcommon/llbase64.h +++ b/indra/llcommon/llbase64.h @@ -32,7 +32,7 @@ */ #ifndef LLBASE64_H -#define LLBASE64_h +#define LLBASE64_H class LL_COMMON_API LLBase64 { diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h index 620a75cdb..f7456eda0 100644 --- a/indra/llcommon/llchat.h +++ b/indra/llcommon/llchat.h @@ -75,14 +75,15 @@ public: : mText(text), mFromName(), mFromID(), -// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) - mRlvLocFiltered(FALSE), - mRlvNamesFiltered(FALSE), -// [/RLVa:KB] + mSourceType(CHAT_SOURCE_AGENT), mChatType(CHAT_TYPE_NORMAL), mAudible(CHAT_AUDIBLE_FULLY), mMuted(FALSE), +// [RLVa:KB] - Checked: 2010-04-22 (RLVa-1.2.0f) | Modified: RLVa-1.0.0a + mRlvLocFiltered(FALSE), + mRlvNamesFiltered(FALSE), +// [/RLVa:KB] mTime(0.0), mPosAgent(), mURL() @@ -104,14 +105,14 @@ public: std::string mText; // UTF-8 line of text std::string mFromName; // agent or object name LLUUID mFromID; // agent id or object id -// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) - BOOL mRlvLocFiltered; - BOOL mRlvNamesFiltered; -// [/RLVa:KB] EChatSourceType mSourceType; EChatType mChatType; EChatAudible mAudible; BOOL mMuted; // pass muted chat to maintain list of chatters +// [RLVa:KB] - Checked: 2010-04-22 (RLVa-1.2.0f) | Modified: RLVa-1.0.0a + BOOL mRlvLocFiltered; + BOOL mRlvNamesFiltered; +// [/RLVa:KB] F64 mTime; // viewer only, seconds from viewer start LLVector3 mPosAgent; std::string mURL; diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 298dd4695..33b30ac72 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -39,7 +39,6 @@ void LLCommon::initClass() { LLMemory::initClass(); LLTimer::initClass(); - LLThreadSafeRefCount::initThreadSafeRefCount(); // LLWorkerThread::initClass(); // LLFrameCallbackManager::initClass(); } @@ -49,7 +48,6 @@ void LLCommon::cleanupClass() { // LLFrameCallbackManager::cleanupClass(); // LLWorkerThread::cleanupClass(); - LLThreadSafeRefCount::cleanupThreadSafeRefCount(); LLTimer::cleanupClass(); LLMemory::cleanupClass(); } diff --git a/indra/llcommon/llcursortypes.cpp b/indra/llcommon/llcursortypes.cpp index 7444115aa..916ac8a91 100644 --- a/indra/llcommon/llcursortypes.cpp +++ b/indra/llcommon/llcursortypes.cpp @@ -30,6 +30,8 @@ * $/LicenseInfo$ */ +#include "linden_common.h" + #include "llcursortypes.h" ECursorType getCursorFromString(const std::string& cursor_string) @@ -66,14 +68,14 @@ ECursorType getCursorFromString(const std::string& cursor_string) cursor_string_table["UI_CURSOR_TOOLPAN"] = UI_CURSOR_TOOLPAN; cursor_string_table["UI_CURSOR_TOOLZOOMIN"] = UI_CURSOR_TOOLZOOMIN; cursor_string_table["UI_CURSOR_TOOLPICKOBJECT3"] = UI_CURSOR_TOOLPICKOBJECT3; - cursor_string_table["UI_CURSOR_TOOLSIT"] = UI_CURSOR_TOOLSIT; - cursor_string_table["UI_CURSOR_TOOLBUY"] = UI_CURSOR_TOOLBUY; - cursor_string_table["UI_CURSOR_TOOLPAY"] = UI_CURSOR_TOOLPAY; - cursor_string_table["UI_CURSOR_TOOLOPEN"] = UI_CURSOR_TOOLOPEN; cursor_string_table["UI_CURSOR_TOOLPLAY"] = UI_CURSOR_TOOLPLAY; cursor_string_table["UI_CURSOR_TOOLPAUSE"] = UI_CURSOR_TOOLPAUSE; cursor_string_table["UI_CURSOR_TOOLMEDIAOPEN"] = UI_CURSOR_TOOLMEDIAOPEN; cursor_string_table["UI_CURSOR_PIPETTE"] = UI_CURSOR_PIPETTE; + cursor_string_table["UI_CURSOR_TOOLSIT"] = UI_CURSOR_TOOLSIT; + cursor_string_table["UI_CURSOR_TOOLBUY"] = UI_CURSOR_TOOLBUY; + cursor_string_table["UI_CURSOR_TOOLPAY"] = UI_CURSOR_TOOLPAY; + cursor_string_table["UI_CURSOR_TOOLOPEN"] = UI_CURSOR_TOOLOPEN; } std::map::const_iterator iter = cursor_string_table.find(cursor_string); diff --git a/indra/llcommon/llcursortypes.h b/indra/llcommon/llcursortypes.h index 836ecc3c0..e95cbc127 100644 --- a/indra/llcommon/llcursortypes.h +++ b/indra/llcommon/llcursortypes.h @@ -33,8 +33,6 @@ #ifndef LL_LLCURSORTYPES_H #define LL_LLCURSORTYPES_H -#include "linden_common.h" - // If you add types here, add them in LLCursor::getCursorFromString enum ECursorType { UI_CURSOR_ARROW, @@ -66,14 +64,14 @@ enum ECursorType { UI_CURSOR_TOOLPAN, UI_CURSOR_TOOLZOOMIN, UI_CURSOR_TOOLPICKOBJECT3, - UI_CURSOR_TOOLSIT, - UI_CURSOR_TOOLBUY, - UI_CURSOR_TOOLPAY, - UI_CURSOR_TOOLOPEN, UI_CURSOR_TOOLPLAY, UI_CURSOR_TOOLPAUSE, UI_CURSOR_TOOLMEDIAOPEN, UI_CURSOR_PIPETTE, + UI_CURSOR_TOOLSIT, + UI_CURSOR_TOOLBUY, + UI_CURSOR_TOOLPAY, + UI_CURSOR_TOOLOPEN, UI_CURSOR_COUNT // Number of elements in this enum (NOT a cursor) }; diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index da3d0763a..c537a76a8 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -402,7 +402,7 @@ namespace { /* This pattern, of returning a reference to a static function variable, is to ensure that this global is constructed before - it is used, no matter what the global initializeation sequence + it is used, no matter what the global initialization sequence is. See C++ FAQ Lite, sections 10.12 through 10.14 */ diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index e04e59d53..34934c5c2 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -45,7 +45,7 @@ Information for most users: - Code can log messages with constuctions like this: + Code can log messages with constructions like this: LL_INFOS("StringTag") << "request to fizzbip agent " << agent_id << " denied due to timeout" << LL_ENDL; @@ -53,9 +53,9 @@ Messages can be logged to one of four increasing levels of concern, using one of four "streams": - LL_DEBUGS("StringTag") - debug messages that are normally supressed - LL_INFOS("StringTag") - informational messages that are normall shown - LL_WARNS("StringTag") - warning messages that singal a problem + LL_DEBUGS("StringTag") - debug messages that are normally suppressed + LL_INFOS("StringTag") - informational messages that are normally shown + LL_WARNS("StringTag") - warning messages that signal a problem LL_ERRS("StringTag") - error messages that are major, unrecoverable failures The later (LL_ERRS("StringTag")) automatically crashes the process after the message @@ -96,7 +96,7 @@ WARN: LLFoo::doSomething: called with a big value for i: 283 - Which messages are logged and which are supressed can be controled at run + Which messages are logged and which are suppressed can be controlled at run time from the live file logcontrol.xml based on function, class and/or source file. See etc/logcontrol-dev.xml for details. @@ -112,7 +112,7 @@ namespace LLError enum ELevel { LEVEL_ALL = 0, - // used to indicate that all messagess should be logged + // used to indicate that all messages should be logged LEVEL_DEBUG = 0, LEVEL_INFO = 1, @@ -226,7 +226,7 @@ namespace LLError // See top of file for example of how to use this typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; - // Outside a class declartion, or in class without LOG_CLASS(), this + // Outside a class declaration, or in class without LOG_CLASS(), this // typedef causes the messages to not be associated with any class. diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp index 293379910..8476d0bfe 100644 --- a/indra/llcommon/llerrorthread.cpp +++ b/indra/llcommon/llerrorthread.cpp @@ -31,6 +31,7 @@ #include "linden_common.h" #include "llerrorthread.h" + #include "llapp.h" #include "lltimer.h" // ms_sleep() @@ -117,13 +118,8 @@ void LLErrorThread::run() #if !LL_WINDOWS U32 last_sig_child_count = 0; #endif - while (1) + while (! (LLApp::isError() || LLApp::isStopped())) { - if (LLApp::isError() || LLApp::isStopped()) - { - // The application has stopped running, time to take action (maybe) - break; - } #if !LL_WINDOWS // Check whether or not the main thread had a sig child we haven't handled. U32 current_sig_child_count = LLApp::getSigChildCount(); diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index d3e97f5c1..0d8dce1eb 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -35,6 +35,8 @@ #if LL_WINDOWS #include +#else +#include #endif #include "linden_common.h" diff --git a/indra/llcommon/llhash.h b/indra/llcommon/llhash.h index 0ce10883a..c0a8bff66 100644 --- a/indra/llcommon/llhash.h +++ b/indra/llcommon/llhash.h @@ -39,15 +39,15 @@ #include #include #elif LL_DARWIN || LL_LINUX -# if GCC_VERSION >= 40300 // gcc 4.3 and up -# include -# elif GCC_VERSION >= 30400 // gcc 3.4 and up -# include -# elif __GNUC__ >= 3 -# include -# else -# include -# endif +#if GCC_VERSION >= 40300 || LL_ICC// gcc 4.3 or icc 11 and up +# include +#elif GCC_VERSION >= 30400 // gcc 3.4 and up +# include +#elif __GNUC__ >= 3 +# include +#else +# include +#endif #elif LL_SOLARIS #include #else diff --git a/indra/llcommon/llheartbeat.cpp b/indra/llcommon/llheartbeat.cpp index 49c0ad508..83cf3e50c 100644 --- a/indra/llcommon/llheartbeat.cpp +++ b/indra/llcommon/llheartbeat.cpp @@ -75,7 +75,7 @@ LLHeartbeat::rawSend() int result; #ifndef LL_DARWIN - union sigval dummy; + static union sigval dummy; result = sigqueue(getppid(), LL_HEARTBEAT_SIGNAL, dummy); #else result = kill(getppid(), LL_HEARTBEAT_SIGNAL); diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h index 590718687..8bf715f14 100644 --- a/indra/llcommon/llmd5.h +++ b/indra/llcommon/llmd5.h @@ -134,7 +134,4 @@ private: LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b); LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b); -LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b); -LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b); - #endif // LL_LLMD5_H diff --git a/indra/llcommon/lloptioninterface.h b/indra/llcommon/lloptioninterface.h index 4faf95f5e..dd5829d79 100644 --- a/indra/llcommon/lloptioninterface.h +++ b/indra/llcommon/lloptioninterface.h @@ -39,7 +39,7 @@ class LLSD; class LLOptionInterface { public: - virtual ~LLOptionInterface() = 0; + virtual ~LLOptionInterface(); virtual LLSD getOption(const std::string& name) const = 0; }; diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index a956718e6..009871908 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -78,7 +78,18 @@ // Figure out differences between compilers -#if defined(__GNUC__) +#if defined(__clang__) && defined(__GNUC__) + #define CLANG_VERSION (__clang_major__ * 10000 \ + + __clang_minor__ * 100 \ + + __clang_patchlevel__) + #ifndef LL_CLANG + #define LL_CLANG 1 + #endif +#elif defined (__ICC) && defined(__GNUC__) + #ifndef LL_ICC + #define LL_ICC 1 + #endif +#elif defined(__GNUC__) #define GCC_VERSION (__GNUC__ * 10000 \ + __GNUC_MINOR__ * 100 \ + __GNUC_PATCHLEVEL__) diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp index 8ffd4b06d..8e146e035 100644 --- a/indra/llcommon/llprocesslauncher.cpp +++ b/indra/llcommon/llprocesslauncher.cpp @@ -42,6 +42,7 @@ #if LL_DARWIN || LL_LINUX // not required or present on Win32 #include +#include #endif LLProcessLauncher::LLProcessLauncher() diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index f255e5a8b..dee0d50e1 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -55,10 +55,10 @@ # define LL_X86 1 #elif LL_MSVC && _M_IX86 # define LL_X86 1 -#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) ) +#elif LL_GNUC || LL_ICC || LL_CLANG && ( defined(__amd64__) || defined(__x86_64__) ) # define LL_X86_64 1 # define LL_X86 1 -#elif LL_GNUC && ( defined(__i386__) ) +#elif LL_GNUC || LL_ICC || LL_CLANG && ( defined(__i386__) ) # define LL_X86 1 #elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) ) # define LL_PPC 1 diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index ab73670ae..2680072bc 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -44,7 +44,7 @@ #include "llsimplehash.h" //============================================================================ -// Note: ~LLQueuedThread is O(N) N=# of queued threads, assumed to be small +// Note: ~LLQueuedThread is O(N) N=# of queued requests, assumed to be small // It is assumed that LLQueuedThreads are rarely created/destroyed. class LL_COMMON_API LLQueuedThread : public LLThread diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index b7e7e1dca..7d1b80710 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -50,6 +50,16 @@ public: const LLStrider& operator = (Object *first) { mObjectp = first; return *this;} void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));} + + LLStrider operator+(const S32& index) + { + LLStrider ret; + ret.mBytep = mBytep + mSkip*index; + ret.mSkip = mSkip; + + return ret; + } + //void setTypeSize (S32 typeBytes){ mTypeSize = (typeBytes ? typeBytes : sizeof(Object)); } //bool isStrided() const { return mTypeSize != mSkip; } diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index f9128b574..7c159c830 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -737,6 +737,7 @@ std::string LLStringOps::sDayFormat; std::string LLStringOps::sAM; std::string LLStringOps::sPM; + S32 LLStringOps::collate(const llwchar* a, const llwchar* b) { #if LL_WINDOWS @@ -936,22 +937,24 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions); template<> void LLStringUtil::getTokens(const std::string& instr, std::vector& tokens, const std::string& delims) { - std::string currToken; - std::string::size_type begIdx, endIdx; - - begIdx = instr.find_first_not_of (delims); - while (begIdx != std::string::npos) + // Starting at offset 0, scan forward for the next non-delimiter. We're + // done when the only characters left in 'instr' are delimiters. + for (std::string::size_type begIdx, endIdx = 0; + (begIdx = instr.find_first_not_of (delims, endIdx)) != std::string::npos; ) { + // Found a non-delimiter. After that, find the next delimiter. endIdx = instr.find_first_of (delims, begIdx); if (endIdx == std::string::npos) { + // No more delimiters: this token extends to the end of the string. endIdx = instr.length(); } - currToken = instr.substr(begIdx, endIdx - begIdx); + // extract the token between begIdx and endIdx; substr() needs length + std::string currToken(instr.substr(begIdx, endIdx - begIdx)); LLStringUtil::trim (currToken); tokens.push_back(currToken); - begIdx = instr.find_first_not_of (delims, endIdx); + // next scan past delimiters starts at endIdx } } @@ -1401,7 +1404,7 @@ void LLStringUtilBase::testHarness() s2.erase( 4, 1 ); llassert( s2 == "hell"); - s2.insert( 0, 'y' ); + s2.insert( 0, 1, 'y' ); llassert( s2 == "yhell"); s2.erase( 1, 3 ); llassert( s2 == "yl"); diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 803db8c3d..3716e5dab 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -68,6 +68,7 @@ U32 ll_thread_local local_thread_ID = 0; U32 LLThread::sIDIter = 0; LLAtomicS32 LLThread::sCount = 0; +LLAtomicS32 LLThread::sRunning = 0; LL_COMMON_API void assert_main_thread() { @@ -104,6 +105,11 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap // the moment it happens... therefore make a copy here. char const* volatile name = threadp->mName.c_str(); + // Always make sure that sRunning <= number of threads with status RUNNING, + // so do this before changing mStatus (meaning that once we see that we + // are STOPPED, then sRunning is also up to date). + --sRunning; + // We're done with the run function, this thread is done executing now. threadp->mStatus = STOPPED; @@ -114,6 +120,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap // the critical area of the mSignal lock)]. lldebugs << "LLThread::staticRun() Exiting: " << name << llendl; + --sRunning; // Would be better to do this after joining with the thread, but we don't join :/ return NULL; } @@ -178,7 +185,7 @@ void LLThread::shutdown() } mAPRThreadp = NULL; } - sCount--; + --sCount; delete mRunCondition; mRunCondition = 0; } @@ -189,6 +196,7 @@ void LLThread::start() // Set thread state to running mStatus = RUNNING; + sRunning++; apr_status_t status = apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool()); @@ -200,6 +208,7 @@ void LLThread::start() } else { + --sRunning; mStatus = STOPPED; llwarns << "failed to start thread " << mName << llendl; ll_apr_warn_status(status); @@ -402,6 +411,15 @@ LLMutexBase::LLMutexBase() : { } +bool LLMutexBase::isSelfLocked() const +{ +#if LL_DARWIN + return mLockingThread == LLThread::currentID(); +#else + return mLockingThread == local_thread_ID; +#endif +} + void LLMutexBase::lock() { #if LL_DARWIN @@ -435,37 +453,6 @@ void LLMutexBase::unlock() apr_thread_mutex_unlock(mAPRMutexp); } -bool LLMutexBase::isSelfLocked() -{ -#if LL_DARWIN - return mLockingThread == LLThread::currentID(); -#else - return mLockingThread == local_thread_ID; -#endif -} - -//---------------------------------------------------------------------------- - -//static -LLMutex* LLThreadSafeRefCount::sMutex = 0; - -//static -void LLThreadSafeRefCount::initThreadSafeRefCount() -{ - if (!sMutex) - { - sMutex = new LLMutex; - } -} - -//static -void LLThreadSafeRefCount::cleanupThreadSafeRefCount() -{ - delete sMutex; - sMutex = NULL; -} - - //---------------------------------------------------------------------------- LLThreadSafeRefCount::LLThreadSafeRefCount() : diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 2509ecf84..8def2c7ea 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -38,9 +38,13 @@ #include "llmemory.h" #include "apr_thread_cond.h" #include "llaprpool.h" +#include "llatomic.h" #ifdef SHOW_ASSERT extern LL_COMMON_API bool is_main_thread(void); +#define ASSERT_SINGLE_THREAD do { static apr_os_thread_t first_thread_id = apr_os_thread_current(); llassert(apr_os_thread_equal(first_thread_id, apr_os_thread_current())); } while(0) +#else +#define ASSERT_SINGLE_THREAD do { } while(0) #endif class LLThread; @@ -74,7 +78,8 @@ class LL_COMMON_API LLThread private: static U32 sIDIter; static LLAtomicS32 sCount; - + static LLAtomicS32 sRunning; + public: typedef enum e_thread_status { @@ -92,8 +97,9 @@ public: static U32 currentID(); // Return ID of current thread static S32 getCount() { return sCount; } + static S32 getRunning() { return sRunning; } static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure. - + public: // PAUSE / RESUME functionality. See source code for important usage notes. // Called from MAIN THREAD. @@ -181,15 +187,18 @@ public: LLMutexBase() ; - void lock(); //blocks + void lock(); // blocks void unlock(); // Returns true if lock was obtained successfully. bool tryLock() { return !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)); } // non-blocking, but does do a lock/unlock so not free bool isLocked() { bool is_not_locked = tryLock(); if (is_not_locked) unlock(); return !is_not_locked; } + + // Returns true if locked by this thread. + bool isSelfLocked() const; + // get ID of locking thread - bool isSelfLocked(); //return true if locked in a same thread U32 lockingThread() const { return mLockingThread; } protected: @@ -373,6 +382,16 @@ public: mNoHoldersCondition.signal(); // Tell waiting readers, see [5]. mNoHoldersCondition.unlock(); // Release lock on mHoldersCount. } +#if LL_DEBUG + // Really only intended for debugging purposes: + bool isLocked(void) + { + mNoHoldersCondition.lock(); + bool res = mHoldersCount; + mNoHoldersCondition.unlock(); + return res; + } +#endif }; //============================================================================ @@ -394,13 +413,6 @@ void LLThread::unlockData() class LL_COMMON_API LLThreadSafeRefCount { -public: - static void initThreadSafeRefCount(); // creates sMutex - static void cleanupThreadSafeRefCount(); // destroys sMutex - -private: - static LLMutex* sMutex; - private: LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented @@ -413,31 +425,20 @@ public: void ref() { - if (sMutex) sMutex->lock(); mRef++; - if (sMutex) sMutex->unlock(); } - S32 unref() + void unref() { - llassert(mRef >= 1); - if (sMutex) sMutex->lock(); - S32 res = --mRef; - if (sMutex) sMutex->unlock(); - if (0 == res) - { - delete this; - return 0; - } - return res; - } + if (!--mRef) delete this; + } S32 getNumRefs() const { return mRef; } private: - S32 mRef; + LLAtomicS32 mRef; }; //============================================================================ diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt index 5891b154c..97989030a 100644 --- a/indra/llimage/CMakeLists.txt +++ b/indra/llimage/CMakeLists.txt @@ -8,12 +8,15 @@ include(LLCommon) include(LLImage) include(LLMath) include(LLVFS) +include(JPEG) +include(PNG) include(ZLIB) include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} + ${JPEG_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} ) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index d6c2074f2..c3f4878ee 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -269,7 +269,7 @@ U8* LLImageBase::allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 si // LLImageRaw //--------------------------------------------------------------------------- -AITHREADSAFESIMPLE(S32, LLImageRaw::sGlobalRawMemory, ); +AIThreadSafeSimpleDC LLImageRaw::sGlobalRawMemory; S32 LLImageRaw::sRawImageCount = 0; S32 LLImageRaw::sRawImageCachedCount = 0; diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index b58dd5931..3eaf74b04 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -248,7 +248,7 @@ protected: void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; public: - static AIThreadSafeSimple sGlobalRawMemory; + static AIThreadSafeSimpleDC sGlobalRawMemory; static S32 sRawImageCount; static S32 sRawImageCachedCount; diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp index c81126812..34c679352 100644 --- a/indra/llimage/llimagedxt.cpp +++ b/indra/llimage/llimagedxt.cpp @@ -1,37 +1,32 @@ /** * @file llimagedxt.cpp * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "linden_common.h" #include "llimagedxt.h" +#include "llmemory.h" //static void LLImageDXT::checkMinWidthHeight(EFileFormat format, S32& width, S32& height) diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 63d06e338..b39ae0c04 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -363,8 +363,12 @@ S32 LLImageJ2C::calcHeaderSizeJ2C() return FIRST_PACKET_SIZE; // Hack. just needs to be >= actual header size... } -static S32 cald_data_size_help(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate) +//static +S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate) { + // Note: this only provides an *estimate* of the size in bytes of an image level + // *TODO: find a way to read the true size (when available) and convey the fact + // that the result is an estimate in the other cases if (rate <= 0.f) rate = .125f; while (discard_level > 0) { @@ -375,22 +379,7 @@ static S32 cald_data_size_help(S32 w, S32 h, S32 comp, S32 discard_level, F32 ra discard_level--; } S32 bytes = (S32)((F32)(w*h*comp)*rate); - return bytes; -} - - -//static -S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate) -{ - static const LLCachedControl exponent("SianaJ2CSizeExponent", 1.0f); - static const LLCachedControl offset("SianaJ2CSizeOffset", 0); - S32 size = cald_data_size_help(w, h, comp, discard_level, rate); - S32 size_d0 = cald_data_size_help(w, h, comp, 0, rate); - - llassert_always(size_d0); - S32 bytes = size_d0*pow((double)size/size_d0, (double)exponent) + offset; - bytes = llmax (0, bytes - 600); - bytes = ((bytes + (1000 - 1))/1000)*1000 + 600; + bytes = llmax(bytes, calcHeaderSizeJ2C()); return bytes; } diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp index 33b1ab181..34f553ffc 100644 --- a/indra/llimage/llimagepng.cpp +++ b/indra/llimage/llimagepng.cpp @@ -2,31 +2,25 @@ * @file llimagepng.cpp * @brief LLImageFormatted glue to encode / decode PNG files. * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -66,6 +60,12 @@ BOOL LLImagePNG::updateData() // Decode the PNG data and extract sizing information LLPngWrapper pngWrapper; + if (!pngWrapper.isValidPng(getData())) + { + setLastError("LLImagePNG data does not have a valid PNG header!"); + return FALSE; + } + LLPngWrapper::ImageInfo infop; if (! pngWrapper.readPng(getData(), NULL, &infop)) { @@ -96,6 +96,12 @@ BOOL LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time) // Decode the PNG data into the raw image LLPngWrapper pngWrapper; + if (!pngWrapper.isValidPng(getData())) + { + setLastError("LLImagePNG data does not have a valid PNG header!"); + return FALSE; + } + if (! pngWrapper.readPng(getData(), raw_image)) { setLastError(pngWrapper.getErrorMessage()); diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp index a6721bfa0..58426d31f 100644 --- a/indra/llimage/llimagetga.cpp +++ b/indra/llimage/llimagetga.cpp @@ -1,40 +1,36 @@ /** * @file llimagetga.cpp * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "linden_common.h" -#include "lldir.h" #include "llimagetga.h" + +#include "lldir.h" #include "llerror.h" #include "llmath.h" +#include "llpointer.h" // For expanding 5-bit pixel values to 8-bit with best rounding // static diff --git a/indra/llimage/llpngwrapper.h b/indra/llimage/llpngwrapper.h index eb47fdbdd..a4c3d80b5 100644 --- a/indra/llimage/llpngwrapper.h +++ b/indra/llimage/llpngwrapper.h @@ -32,11 +32,7 @@ #ifndef LL_LLPNGWRAPPER_H #define LL_LLPNGWRAPPER_H -#if LL_WINDOWS -#include "libpng15/png.h" -#else -#include "libpng12/png.h" -#endif +#include "png.h" #include "llimage.h" class LLPngWrapper diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index cde11493f..743c7a347 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -2,31 +2,25 @@ * @file llimagej2coj.cpp * @brief This is an implementation of JPEG2000 encode/decode using OpenJPEG. * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,7 +31,7 @@ #include "openjpeg.h" #include "lltimer.h" -#include "llmemory.h" +//#include "llmemory.h" const char* fallbackEngineInfoLLImageJ2CImpl() { @@ -96,8 +90,15 @@ void info_callback(const char* msg, void*) lldebugs << "LLImageJ2COJ: " << chomp(msg) << llendl; } +// Divide a by 2 to the power of b and round upwards +int ceildivpow2(int a, int b) +{ + return (a + (1 << b) - 1) >> b; +} -LLImageJ2COJ::LLImageJ2COJ() : LLImageJ2CImpl() + +LLImageJ2COJ::LLImageJ2COJ() + : LLImageJ2CImpl() { } @@ -180,7 +181,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod // dereference the array. if(!image || !image->numcomps) { - llwarns << "failed to decode image!" << llendl; + LL_WARNS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL; if (image) { opj_image_destroy(image); @@ -195,7 +196,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod { if (image->comps[i].factor != base.getRawDiscardLevel()) { - llwarns << "Expected discard level not reached!" << llendl; + LL_WARNS("Texture") << "Expected discard level not reached!" << llendl; // if we didn't get the discard level we're expecting, fail opj_image_destroy(image); base.decodeFailed(); @@ -256,7 +257,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod } else // Some rare OpenJPEG versions have this bug. { - llwarns << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << llendl; + LL_WARNS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << llendl; opj_image_destroy(image); base.decodeFailed(); @@ -391,7 +392,7 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con if (!bSuccess) { opj_cio_close(cio); - llinfos << "Failed to encode image." << llendl; + LL_WARNS("Texture") << "Failed to encode image." << llendl; return FALSE; } codestream_length = cio_tell(cio); diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index adad26591..c34b89e37 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -45,9 +45,8 @@ #include "llsdutil.h" ///---------------------------------------------------------------------------- -/// exported functions +/// Exported functions ///---------------------------------------------------------------------------- - static const std::string INV_ITEM_ID_LABEL("item_id"); static const std::string INV_FOLDER_ID_LABEL("folder_id"); static const std::string INV_PARENT_ID_LABEL("parent_id"); @@ -423,7 +422,7 @@ U32 LLInventoryItem::getCRC32() const //lldebugs << "7 crc: " << std::hex << crc << std::dec << llendl; crc += mSaleInfo.getCRC32(); //lldebugs << "8 crc: " << std::hex << crc << std::dec << llendl; - crc += mCreationDate; + crc += (U32)mCreationDate; //lldebugs << "9 crc: " << std::hex << crc << std::dec << llendl; return crc; } @@ -539,7 +538,7 @@ void LLInventoryItem::packMessage(LLMessageSystem* msg) const mSaleInfo.packMessage(msg); msg->addStringFast(_PREHASH_Name, mName); msg->addStringFast(_PREHASH_Description, mDescription); - msg->addS32Fast(_PREHASH_CreationDate, mCreationDate); + msg->addS32Fast(_PREHASH_CreationDate, (S32)mCreationDate); U32 crc = getCRC32(); msg->addU32Fast(_PREHASH_CRC, crc); } @@ -1199,109 +1198,8 @@ fail: } -LLXMLNode *LLInventoryItem::exportFileXML(BOOL include_asset_key) const -{ - LLMemType m1(LLMemType::MTYPE_INVENTORY); - LLXMLNode *ret = new LLXMLNode("item", FALSE); - - ret->createChild("uuid", TRUE)->setUUIDValue(1, &mUUID); - ret->createChild("parent_uuid", TRUE)->setUUIDValue(1, &mParentUUID); - - mPermissions.exportFileXML()->setParent(ret); - - // Check for permissions to see the asset id, and if so write it - // out as an asset id. Otherwise, apply our cheesy encryption. - if(include_asset_key) - { - U32 mask = mPermissions.getMaskBase(); - if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - || (mAssetUUID.isNull())) - { - ret->createChild("asset_id", FALSE)->setUUIDValue(1, &mAssetUUID); - } - else - { - LLUUID shadow_id(mAssetUUID); - LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); - cipher.encrypt(shadow_id.mData, UUID_BYTES); - - ret->createChild("shadow_id", FALSE)->setUUIDValue(1, &shadow_id); - } - } - - std::string type_str = LLAssetType::lookup(mType); - std::string inv_type_str = LLInventoryType::lookup(mInventoryType); - - ret->createChild("asset_type", FALSE)->setStringValue(type_str); - ret->createChild("inventory_type", FALSE)->setStringValue(inv_type_str); - S32 tmp_flags = (S32) mFlags; - ret->createChild("flags", FALSE)->setByteValue(4, (U8*)(&tmp_flags), LLXMLNode::ENCODING_HEX); - - mSaleInfo.exportFileXML()->setParent(ret); - - std::string temp; - temp.assign(mName); - ret->createChild("name", FALSE)->setStringValue(temp); - temp.assign(mDescription); - ret->createChild("description", FALSE)->setStringValue(temp); - S32 date = mCreationDate; - ret->createChild("creation_date", FALSE)->setIntValue(1, &date); - - return ret; -} - -BOOL LLInventoryItem::importXML(LLXMLNode* node) -{ - BOOL success = FALSE; - if (node) - { - success = TRUE; - LLXMLNodePtr sub_node; - if (node->getChild("uuid", sub_node)) - success = (1 == sub_node->getUUIDValue(1, &mUUID)); - if (node->getChild("parent_uuid", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mParentUUID)); - if (node->getChild("permissions", sub_node)) - success = success && mPermissions.importXML(sub_node); - if (node->getChild("asset_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mAssetUUID)); - if (node->getChild("shadow_id", sub_node)) - { - success = success && (1 == sub_node->getUUIDValue(1, &mAssetUUID)); - LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); - cipher.decrypt(mAssetUUID.mData, UUID_BYTES); - } - if (node->getChild("asset_type", sub_node)) - mType = LLAssetType::lookup(sub_node->getValue()); - if (node->getChild("inventory_type", sub_node)) - mInventoryType = LLInventoryType::lookup(sub_node->getValue()); - if (node->getChild("flags", sub_node)) - { - S32 tmp_flags = 0; - success = success && (1 == sub_node->getIntValue(1, &tmp_flags)); - mFlags = (U32) tmp_flags; - } - if (node->getChild("sale_info", sub_node)) - success = success && mSaleInfo.importXML(sub_node); - if (node->getChild("name", sub_node)) - mName = sub_node->getValue(); - if (node->getChild("description", sub_node)) - mDescription = sub_node->getValue(); - if (node->getChild("creation_date", sub_node)) - { - S32 date = 0; - success = success && (1 == sub_node->getIntValue(1, &date)); - mCreationDate = date; - } - - if (!success) - { - lldebugs << "LLInventory::importXML() failed for node named '" - << node->getName() << "'" << llendl; - } - } - return success; -} +// Deleted LLInventoryItem::exportFileXML() and LLInventoryItem::importXML() +// because I can't find any non-test code references to it. 2009-05-04 JC S32 LLInventoryItem::packBinaryBucket(U8* bin_bucket, LLPermissions* perm_override) const { diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index 479c7d397..14c04a0d1 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -214,15 +214,11 @@ public: virtual BOOL importLegacyStream(std::istream& input_stream); virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const; - virtual LLXMLNode *exportFileXML(BOOL include_asset_key = TRUE) const; - BOOL importXML(LLXMLNode* node); - //-------------------------------------------------------------------- // Helper Functions //-------------------------------------------------------------------- public: // Pack all information needed to reconstruct this item into the given binary bucket. - S32 packBinaryBucket(U8* bin_bucket, LLPermissions* perm_override = NULL) const; void unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size); LLSD asLLSD() const; @@ -249,7 +245,6 @@ protected: // items. Users come with a set of default categories, and can create // new ones as needed. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - class LLInventoryCategory : public LLInventoryObject { public: diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index e4e1d239e..e92ae5dc0 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -200,8 +200,6 @@ void LLParcel::init(const LLUUID &owner_id, mMediaWidth = 0; mMediaHeight = 0; setMediaCurrentURL(LLStringUtil::null); - mMediaURLFilterEnable = FALSE; - mMediaURLFilterList = LLSD::emptyArray(); mMediaAllowNavigate = TRUE; mMediaURLTimeout = 0.0f; mMediaPreventCameraZoom = FALSE; @@ -343,38 +341,6 @@ void LLParcel::setMediaURLResetTimer(F32 time) mMediaResetTimer.setTimerExpirySec(time); } -void LLParcel::setMediaURLFilterList(LLSD list) -{ - // sanity check LLSD - // must be array of strings - if (!list.isArray()) - { - return; - } - - for (S32 i = 0; i < list.size(); i++) - { - if (!list[i].isString()) - return; - } - - // can't be too big - const S32 MAX_SIZE = 50; - if (list.size() > MAX_SIZE) - { - LLSD new_list = LLSD::emptyArray(); - - for (S32 i = 0; i < llmin(list.size(), MAX_SIZE); i++) - { - new_list.append(list[i]); - } - - list = new_list; - } - - mMediaURLFilterList = list; -} - // virtual void LLParcel::setLocalID(S32 local_id) { @@ -629,34 +595,6 @@ BOOL LLParcel::importAccessEntry(std::istream& input_stream, LLAccessEntry* entr return input_stream.good(); } -BOOL LLParcel::importMediaURLFilter(std::istream& input_stream, std::string& url) -{ - skip_to_end_of_next_keyword("{", input_stream); - - while(input_stream.good()) - { - skip_comments_and_emptyspace(input_stream); - std::string line, keyword, value; - get_line(line, input_stream, MAX_STRING); - get_keyword_and_value(keyword, value, line); - - if ("}" == keyword) - { - break; - } - else if ("url" == keyword) - { - url = value; - } - else - { - llwarns << "Unknown keyword in parcel media url filter section: <" - << keyword << ">" << llendl; - } - } - return input_stream.good(); -} - // Assumes we are in a block "ParcelData" void LLParcel::packMessage(LLMessageSystem* msg) { @@ -703,8 +641,6 @@ void LLParcel::packMessage(LLSD& msg) msg["media_allow_navigate"] = getMediaAllowNavigate(); msg["media_prevent_camera_zoom"] = getMediaPreventCameraZoom(); msg["media_url_timeout"] = getMediaURLTimeout(); - msg["media_url_filter_enable"] = getMediaURLFilterEnable(); - msg["media_url_filter_list"] = getMediaURLFilterList(); msg["group_id"] = getGroupID(); msg["pass_price"] = mPassPrice; msg["pass_hours"] = mPassHours; @@ -795,7 +731,6 @@ void LLParcel::unpackMessage(LLMessageSystem* msg) msg->getString("MediaLinkSharing", "MediaCurrentURL", buffer); setMediaCurrentURL(buffer); msg->getU8 ( "MediaLinkSharing", "MediaAllowNavigate", mMediaAllowNavigate ); - msg->getU8 ( "MediaLinkSharing", "MediaURLFilterEnable", mMediaURLFilterEnable ); msg->getU8 ( "MediaLinkSharing", "MediaPreventCameraZoom", mMediaPreventCameraZoom ); msg->getF32( "MediaLinkSharing", "MediaURLTimeout", mMediaURLTimeout); } @@ -1256,8 +1191,6 @@ void LLParcel::clearParcel() mMediaWidth = 0; mMediaHeight = 0; setMediaCurrentURL(LLStringUtil::null); - setMediaURLFilterList(LLSD::emptyArray()); - setMediaURLFilterEnable(FALSE); setMediaAllowNavigate(TRUE); setMediaPreventCameraZoom(FALSE); setMediaURLTimeout(0.0f); diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index 3479e5982..492be170b 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -253,8 +253,6 @@ public: void setMediaWidth(S32 width); void setMediaHeight(S32 height); void setMediaCurrentURL(const std::string& url); - void setMediaURLFilterEnable(U8 enable) { mMediaURLFilterEnable = enable; } - void setMediaURLFilterList(LLSD list); void setMediaAllowNavigate(U8 enable) { mMediaAllowNavigate = enable; } void setMediaURLTimeout(F32 timeout) { mMediaURLTimeout = timeout; } void setMediaPreventCameraZoom(U8 enable) { mMediaPreventCameraZoom = enable; } @@ -317,7 +315,6 @@ public: // BOOL importStream(std::istream& input_stream); BOOL importAccessEntry(std::istream& input_stream, LLAccessEntry* entry); // BOOL exportStream(std::ostream& output_stream); - BOOL importMediaURLFilter(std::istream& input_stream, std::string& url); void packMessage(LLMessageSystem* msg); void packMessage(LLSD& msg); @@ -360,8 +357,6 @@ public: U8 getMediaAutoScale() const { return mMediaAutoScale; } U8 getMediaLoop() const { return mMediaLoop; } const std::string& getMediaCurrentURL() const { return mMediaCurrentURL; } - U8 getMediaURLFilterEnable() const { return mMediaURLFilterEnable; } - LLSD getMediaURLFilterList() const { return mMediaURLFilterList; } U8 getMediaAllowNavigate() const { return mMediaAllowNavigate; } F32 getMediaURLTimeout() const { return mMediaURLTimeout; } U8 getMediaPreventCameraZoom() const { return mMediaPreventCameraZoom; } @@ -657,8 +652,6 @@ protected: U8 mMediaLoop; std::string mMediaCurrentURL; LLUUID mMediaID; - U8 mMediaURLFilterEnable; - LLSD mMediaURLFilterList; U8 mMediaAllowNavigate; U8 mMediaPreventCameraZoom; F32 mMediaURLTimeout; diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp index 718dd354a..9683252dc 100644 --- a/indra/llinventory/llpermissions.cpp +++ b/indra/llinventory/llpermissions.cpp @@ -853,67 +853,8 @@ BOOL LLPermissions::exportLegacyStream(std::ostream& output_stream) const return TRUE; } - -LLXMLNode *LLPermissions::exportFileXML() const -{ - LLXMLNode *ret = new LLXMLNode("permissions", FALSE); - - ret->createChild("group_owned", TRUE)->setBoolValue(mIsGroupOwned); - - ret->createChild("base_mask", FALSE)->setByteValue(4, (U8*)&mMaskBase, LLXMLNode::ENCODING_HEX); - ret->createChild("owner_mask", FALSE)->setByteValue(4, (U8*)&mMaskOwner, LLXMLNode::ENCODING_HEX); - ret->createChild("group_mask", FALSE)->setByteValue(4, (U8*)&mMaskGroup, LLXMLNode::ENCODING_HEX); - ret->createChild("everyone_mask", FALSE)->setByteValue(4, (U8*)&mMaskEveryone, LLXMLNode::ENCODING_HEX); - ret->createChild("next_owner_mask", FALSE)->setByteValue(4, (U8*)&mMaskNextOwner, LLXMLNode::ENCODING_HEX); - - ret->createChild("creator_id", FALSE)->setUUIDValue(1, &mCreator); - ret->createChild("owner_id", FALSE)->setUUIDValue(1, &mOwner); - ret->createChild("last_owner_id", FALSE)->setUUIDValue(1, &mLastOwner); - ret->createChild("group_id", FALSE)->setUUIDValue(1, &mGroup); - - return ret; -} - -bool LLPermissions::importXML(LLXMLNode* node) -{ - bool success = false; - if (node) - { - success = true; - LLXMLNodePtr sub_node; - if (node->getChild("base_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskBase)); - if (node->getChild("owner_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskOwner)); - if (node->getChild("group_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskGroup)); - if (node->getChild("everyone_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskEveryone)); - if (node->getChild("next_owner_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskNextOwner)); - - if (node->getChild("creator_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mCreator)); - if (node->getChild("owner_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mOwner)); - if (node->getChild("last_owner_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mLastOwner)); - if (node->getChild("group_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mGroup)); - if (node->getChild("group_owned", sub_node)) - { - BOOL tmpbool = FALSE; - success = success && (1 == sub_node->getBoolValue(1, &tmpbool)); - mIsGroupOwned = (bool)tmpbool; - } - if (!success) - { - lldebugs << "LLPermissions::importXML() failed for node named '" - << node->getName() << "'" << llendl; - } - } - return success; -} +// Deleted LLPermissions::exportFileXML() and LLPermissions::importXML() +// because I can't find any non-test code references to it. 2009-05-04 JC bool LLPermissions::operator==(const LLPermissions &rhs) const { diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h index 9143fdf30..fa20d5c21 100644 --- a/indra/llinventory/llpermissions.h +++ b/indra/llinventory/llpermissions.h @@ -149,7 +149,7 @@ public: const LLUUID& getGroup() const { return mGroup; } // return the agent_id of the last agent owner. Only returns - // LLUUID::null if there has never been a previous owner. + // LLUUID::null if there has never been a previous owner (*note: this is apparently not true, say for textures in inventory, it may return LLUUID::null even if there was a previous owner). const LLUUID& getLastOwner() const { return mLastOwner; } U32 getMaskBase() const { return mMaskBase; } @@ -235,6 +235,7 @@ public: // Last owner doesn't have much in the way of permissions so it's //not too dangerous to do this. void setLastOwner(const LLUUID& last_owner); + // saves last owner, sets owner to uuid null, sets group // owned. group_id must be the group of the object (that's who it // is being deeded to) and the object must be group @@ -324,9 +325,6 @@ public: BOOL importLegacyStream(std::istream& input_stream); BOOL exportLegacyStream(std::ostream& output_stream) const; - LLXMLNode *exportFileXML() const; - bool importXML(LLXMLNode* node); - bool operator==(const LLPermissions &rhs) const; bool operator!=(const LLPermissions &rhs) const; diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp index e51e35e6e..88e7da7ac 100644 --- a/indra/llinventory/llsaleinfo.cpp +++ b/indra/llinventory/llsaleinfo.cpp @@ -135,38 +135,8 @@ bool LLSaleInfo::fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask) return true; } -LLXMLNode *LLSaleInfo::exportFileXML() const -{ - LLXMLNode *ret = new LLXMLNode("sale_info", FALSE); - std::string type_str = ll_safe_string( lookup(mSaleType)); - ret->createChild("type", TRUE)->setStringValue(1, &type_str); - ret->createChild("price", TRUE)->setIntValue(1, &mSalePrice); - return ret; -} - -BOOL LLSaleInfo::importXML(LLXMLNode* node) -{ - BOOL success = FALSE; - if (node) - { - success = TRUE; - LLXMLNodePtr sub_node; - if (node->getChild("type", sub_node)) - { - mSaleType = lookup(sub_node->getValue().c_str()); - } - if (node->getChild("price", sub_node)) - { - success &= (1 == sub_node->getIntValue(1, &mSalePrice)); - } - if (!success) - { - lldebugs << "LLSaleInfo::importXML() failed for node named '" - << node->getName() << "'" << llendl; - } - } - return success; -} +// Deleted LLSaleInfo::exportFileXML() and LLSaleInfo::importXML() +// because I can't find any non-test code references to it. 2009-05-04 JC BOOL LLSaleInfo::importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask) { diff --git a/indra/llinventory/llsaleinfo.h b/indra/llinventory/llsaleinfo.h index d546c49fd..3461a128b 100644 --- a/indra/llinventory/llsaleinfo.h +++ b/indra/llinventory/llsaleinfo.h @@ -101,9 +101,6 @@ public: bool fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask); BOOL importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask); - LLXMLNode *exportFileXML() const; - BOOL importXML(LLXMLNode* node); - LLSD packMessage() const; void unpackMessage(LLSD sales); diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h index 600e17366..e0ad27026 100644 --- a/indra/llmath/llcalcparser.h +++ b/indra/llmath/llcalcparser.h @@ -1,9 +1,26 @@ /* * LLCalcParser.h - * SecondLife - * - * Created by Aimee Walton on 28/09/2008. * Copyright 2008 Aimee Walton. + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2008, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ * */ @@ -157,7 +174,7 @@ private: F32 _log(const F32& a) const { return log(a); } F32 _exp(const F32& a) const { return exp(a); } F32 _fabs(const F32& a) const { return fabs(a); } - F32 _floor(const F32& a) const { return llfloor(a); } + F32 _floor(const F32& a) const { return (F32)llfloor(a); } F32 _ceil(const F32& a) const { return llceil(a); } F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); } diff --git a/indra/llmath/llcoord.h b/indra/llmath/llcoord.h index 9e38fddbd..9b76268af 100644 --- a/indra/llmath/llcoord.h +++ b/indra/llmath/llcoord.h @@ -1,111 +1,112 @@ /** * @file llcoord.h * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef LL_LLCOORD_H #define LL_LLCOORD_H +template class LLCoord; +struct LL_COORD_TYPE_GL; +struct LL_COORD_TYPE_WINDOW; +struct LL_COORD_TYPE_SCREEN; + +typedef LLCoord LLCoordGL; +typedef LLCoord LLCoordWindow; +typedef LLCoord LLCoordScreen; + +struct LLCoordCommon +{ + LLCoordCommon(S32 x, S32 y) : mX(x), mY(y) {} + LLCoordCommon() : mX(0), mY(0) {} + S32 mX; + S32 mY; +}; + // A two-dimensional pixel value -class LLCoord +template +class LLCoord : protected COORD_FRAME { public: - S32 mX; - S32 mY; + typedef LLCoord self_t; + typename COORD_FRAME::value_t mX; + typename COORD_FRAME::value_t mY; LLCoord(): mX(0), mY(0) {} - LLCoord(S32 x, S32 y): mX(x), mY(y) - {} - virtual ~LLCoord() + LLCoord(typename COORD_FRAME::value_t x, typename COORD_FRAME::value_t y): mX(x), mY(y) {} - virtual void set(S32 x, S32 y) { mX = x; mY = y; } + LLCoord(const LLCoordCommon& other) + { + COORD_FRAME::convertFromCommon(other); + } + + LLCoordCommon convert() const + { + return COORD_FRAME::convertToCommon(); + } + + void set(typename COORD_FRAME::value_t x, typename COORD_FRAME::value_t y) { mX = x; mY = y;} + bool operator==(const self_t& other) const { return mX == other.mX && mY == other.mY; } + bool operator!=(const self_t& other) const { return !(*this == other); } + + static const self_t& getTypedCoords(const COORD_FRAME& self) { return static_cast(self); } + static self_t& getTypedCoords(COORD_FRAME& self) { return static_cast(self); } }; - -// GL coordinates start in the client region of a window, -// with left, bottom = 0, 0 -class LLCoordGL : public LLCoord +struct LL_COORD_TYPE_GL { -public: - LLCoordGL() : LLCoord() - {} - LLCoordGL(S32 x, S32 y) : LLCoord(x, y) - {} - bool operator==(const LLCoordGL& other) const { return mX == other.mX && mY == other.mY; } - bool operator!=(const LLCoordGL& other) const { return !(*this == other); } + typedef S32 value_t; + + LLCoordCommon convertToCommon() const + { + const LLCoordGL& self = LLCoordGL::getTypedCoords(*this); + return LLCoordCommon(self.mX, self.mY); + } + + void convertFromCommon(const LLCoordCommon& from) + { + LLCoordGL& self = LLCoordGL::getTypedCoords(*this); + self.mX = from.mX; + self.mY = from.mY; + } }; -//bool operator ==(const LLCoordGL& a, const LLCoordGL& b); - -// Window coords include things like window borders, -// menu regions, etc. -class LLCoordWindow : public LLCoord +struct LL_COORD_TYPE_WINDOW { -public: - LLCoordWindow() : LLCoord() - {} - LLCoordWindow(S32 x, S32 y) : LLCoord(x, y) - {} - bool operator==(const LLCoordWindow& other) const { return mX == other.mX && mY == other.mY; } - bool operator!=(const LLCoordWindow& other) const { return !(*this == other); } + typedef S32 value_t; + + LLCoordCommon convertToCommon() const; + void convertFromCommon(const LLCoordCommon& from); }; - -// Screen coords start at left, top = 0, 0 -class LLCoordScreen : public LLCoord +struct LL_COORD_TYPE_SCREEN { -public: - LLCoordScreen() : LLCoord() - {} - LLCoordScreen(S32 x, S32 y) : LLCoord(x, y) - {} - bool operator==(const LLCoordScreen& other) const { return mX == other.mX && mY == other.mY; } - bool operator!=(const LLCoordScreen& other) const { return !(*this == other); } -}; + typedef S32 value_t; -class LLCoordFont : public LLCoord -{ -public: - F32 mZ; - - LLCoordFont() : LLCoord(), mZ(0.f) - {} - LLCoordFont(S32 x, S32 y, F32 z = 0) : LLCoord(x,y), mZ(z) - {} - - void set(S32 x, S32 y) { LLCoord::set(x,y); mZ = 0.f; } - void set(S32 x, S32 y, F32 z) { mX = x; mY = y; mZ = z; } - bool operator==(const LLCoordFont& other) const { return mX == other.mX && mY == other.mY; } - bool operator!=(const LLCoordFont& other) const { return !(*this == other); } + LLCoordCommon convertToCommon() const; + void convertFromCommon(const LLCoordCommon& from); }; - #endif diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index 9842f4da1..bb6c6deff 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -91,7 +91,7 @@ const F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO; const F32 FP_MAG_THRESHOLD = 0.0000001f; // TODO: Replace with logic like is_approx_equal -inline BOOL is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); } +inline bool is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); } // These functions work by interpreting sign+exp+mantissa as an unsigned // integer. @@ -117,13 +117,13 @@ inline BOOL is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < // WARNING: Infinity is comparable with F32_MAX and negative // infinity is comparable with F32_MIN -inline BOOL is_approx_equal(F32 x, F32 y) +inline bool is_approx_equal(F32 x, F32 y) { const S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02; return (std::abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); } -inline BOOL is_approx_equal(F64 x, F64 y) +inline bool is_approx_equal(F64 x, F64 y) { const S64 COMPARE_MANTISSA_UP_TO_BIT = 0x02; return (std::abs((S32) ((U64&)x - (U64&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 017d48a0e..c8a0875f5 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -309,7 +309,7 @@ public: //is it here? if (isInside(data->getPositionGroup())) { - if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) || + if (((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius())) || (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity))) { //it belongs here #if LL_OCTREE_PARANOIA_CHECK @@ -416,7 +416,7 @@ public: { //we have data mData.erase(data); mElementCount = mData.size(); - notifyRemoval(data); + this->notifyRemoval(data); checkAlive(); return true; } @@ -454,7 +454,7 @@ public: { mData.erase(data); mElementCount = mData.size(); - notifyRemoval(data); + this->notifyRemoval(data); llwarns << "FOUND!" << llendl; checkAlive(); return; @@ -663,7 +663,7 @@ public: //(don't notify listeners of addition) for (U32 i = 0; i < child->getChildCount(); i++) { - addChild(child->getChild(i), TRUE); + this->addChild(child->getChild(i), TRUE); } //destroy child @@ -707,10 +707,10 @@ public: return false; } - if (this->getSize()[0] > data->getBinRadius() && isInside(data->getPositionGroup())) + if (this->getSize()[0] > data->getBinRadius() && this->isInside(data->getPositionGroup())) { //we got it, just act like a branch - oct_node* node = getNodeAt(data); + oct_node* node = this->getNodeAt(data); if (node == this) { LLOctreeNode::insert(data); @@ -723,7 +723,7 @@ public: else if (this->getChildCount() == 0) { //first object being added, just wrap it up - while (!(this->getSize()[0] > data->getBinRadius() && isInside(data->getPositionGroup()))) + while (!(this->getSize()[0] > data->getBinRadius() && this->isInside(data->getPositionGroup()))) { LLVector4a center, size; center = this->getCenter(); @@ -738,7 +738,7 @@ public: } else { - while (!(this->getSize()[0] > data->getBinRadius() && isInside(data->getPositionGroup()))) + while (!(this->getSize()[0] > data->getBinRadius() && this->isInside(data->getPositionGroup()))) { //the data is outside the root node, we need to grow LLVector4a center(this->getCenter()); @@ -764,7 +764,7 @@ public: //clear our children and add the root copy this->clearChildren(); - addChild(newnode); + this->addChild(newnode); } //insert the data diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 457cbf418..8b47a92ea 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1,31 +1,26 @@ /** + * @file llvolume.cpp * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -2102,7 +2097,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge generate(); - if (mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE || mParams.getSculptType() == LL_SCULPT_TYPE_MESH) + if ((mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE) || mParams.getSculptType() == LL_SCULPT_TYPE_MESH) { createVolumeFaces(); } @@ -2905,7 +2900,7 @@ F32 LLVolume::sculptGetSurfaceArea() // compute the area of the quad by taking the length of the cross product of the two triangles LLVector3 cross1 = (p1 - p2) % (p1 - p3); LLVector3 cross2 = (p4 - p2) % (p4 - p3); - area += (cross1.magVec() + cross2.magVec()) / 2.0; + area += (cross1.magVec() + cross2.magVec()) / 2.f; } } @@ -5896,7 +5891,7 @@ F32 find_vertex_score(LLVCacheVertexData& data) } //bonus points for having low valence - F32 valence_boost = powf(data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); + F32 valence_boost = powf((F32)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); score += FindVertexScore_ValenceBoostScale * valence_boost; return score; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 1bcef4401..9999c236d 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -60,6 +60,7 @@ class LLVolumeTriangle; #include "llstrider.h" #include "v4coloru.h" #include "llrefcount.h" +#include "llpointer.h" #include "llfile.h" //============================================================================ @@ -926,6 +927,10 @@ public: LLVector2* mTexCoords; U16* mIndices; + //vertex buffer filled in by LLFace to cache this volume face geometry in vram + // (declared as a LLPointer to LLRefCount to avoid dependency on LLVertexBuffer) + mutable LLPointer mVertexBuffer; + std::vector mEdge; //list of skin weights for rigged volumes diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index 74855bdc4..108aeb118 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -895,25 +895,25 @@ LLSD LLMatrix4::getValue() const void LLMatrix4::setValue(const LLSD& data) { - mMatrix[0][0] = data[0].asReal(); - mMatrix[0][1] = data[1].asReal(); - mMatrix[0][2] = data[2].asReal(); - mMatrix[0][3] = data[3].asReal(); + mMatrix[0][0] = (F32)data[0].asReal(); + mMatrix[0][1] = (F32)data[1].asReal(); + mMatrix[0][2] = (F32)data[2].asReal(); + mMatrix[0][3] = (F32)data[3].asReal(); - mMatrix[1][0] = data[4].asReal(); - mMatrix[1][1] = data[5].asReal(); - mMatrix[1][2] = data[6].asReal(); - mMatrix[1][3] = data[7].asReal(); + mMatrix[1][0] = (F32)data[4].asReal(); + mMatrix[1][1] = (F32)data[5].asReal(); + mMatrix[1][2] = (F32)data[6].asReal(); + mMatrix[1][3] = (F32)data[7].asReal(); - mMatrix[2][0] = data[8].asReal(); - mMatrix[2][1] = data[9].asReal(); - mMatrix[2][2] = data[10].asReal(); - mMatrix[2][3] = data[11].asReal(); + mMatrix[2][0] = (F32)data[8].asReal(); + mMatrix[2][1] = (F32)data[9].asReal(); + mMatrix[2][2] = (F32)data[10].asReal(); + mMatrix[2][3] = (F32)data[11].asReal(); - mMatrix[3][0] = data[12].asReal(); - mMatrix[3][1] = data[13].asReal(); - mMatrix[3][2] = data[14].asReal(); - mMatrix[3][3] = data[15].asReal(); + mMatrix[3][0] = (F32)data[12].asReal(); + mMatrix[3][1] = (F32)data[13].asReal(); + mMatrix[3][2] = (F32)data[14].asReal(); + mMatrix[3][3] = (F32)data[15].asReal(); } diff --git a/indra/llmath/v4color.cpp b/indra/llmath/v4color.cpp index 219b06ec7..660f59fbe 100644 --- a/indra/llmath/v4color.cpp +++ b/indra/llmath/v4color.cpp @@ -704,9 +704,9 @@ BOOL LLColor4::parseColor(const std::string& buf, LLColor4* color) { color->set(LLColor4::orange6); } - else if ( "clear" == color_name ) + else if ( "clear" == color_name || "transparent" == color_name ) { - color->set(0.f, 0.f, 0.f, 0.f); + color->set(LLColor4::transparent); } else { diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index a328d16e0..b09245ba3 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -34,7 +34,6 @@ set(llmessage_SOURCE_FILES lldispatcher.cpp llfiltersd2xmlrpc.cpp llhost.cpp - llhttpassetstorage.cpp llhttpclient.cpp llhttpclientadapter.cpp llhttpnode.cpp @@ -125,7 +124,6 @@ set(llmessage_HEADER_FILES llfiltersd2xmlrpc.h llfollowcamparams.h llhost.h - llhttpassetstorage.h llhttpclient.h llhttpclientinterface.h llhttpclientadapter.h diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 4add3009f..07d4854c4 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -48,7 +48,7 @@ namespace LLAvatarNameCache // supports it. bool sUseDisplayNames = true; -// [RLVa:KB] - Checked: 2010-12-08 (RLVa-1.2.2c) | Added: RLVa-1.2.2c +// [RLVa:KB] - Checked: 2010-12-08 (RLVa-1.4.0a) | Added: RLVa-1.2.2c // RLVa override for display names bool sForceDisplayNames = false; // [/RLVa:KB] @@ -733,7 +733,7 @@ void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot) } } -// [RLVa:KB] - Checked: 2010-12-08 (RLVa-1.2.2c) | Added: RLVa-1.2.2c +// [RLVa:KB] - Checked: 2010-12-08 (RLVa-1.4.0a) | Added: RLVa-1.2.2c bool LLAvatarNameCache::getForceDisplayNames() { return sForceDisplayNames; @@ -751,7 +751,7 @@ void LLAvatarNameCache::setForceDisplayNames(bool force) void LLAvatarNameCache::setUseDisplayNames(bool use) { -// [RLVa:KB] - Checked: 2010-12-08 (RLVa-1.2.2c) | Added: RLVa-1.2.2c +// [RLVa:KB] - Checked: 2010-12-08 (RLVa-1.4.0a) | Added: RLVa-1.2.2c // We need to force the use of the "display names" cache when @shownames=n restricted (and disallow toggling it) use |= getForceDisplayNames(); // [/RLVa:KB] diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index 41eb64a06..3846463f1 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -80,7 +80,7 @@ namespace LLAvatarNameCache void setUseDisplayNames(bool use); bool useDisplayNames(); -// [RLVa:KB] - Checked: 2010-12-08 (RLVa-1.2.2c) | Added: RLVa-1.2.2c +// [RLVa:KB] - Checked: 2010-12-08 (RLVa-1.4.0a) | Added: RLVa-1.2.2c bool getForceDisplayNames(); void setForceDisplayNames(bool force); // [/RLVa:KB] diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp index e0410906f..4b41abd45 100644 --- a/indra/llmessage/llcircuit.cpp +++ b/indra/llmessage/llcircuit.cpp @@ -688,7 +688,7 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent) // now, check to see if we've got a gap U32 gap = 0; - if ((mPacketsInID == id)) + if (mPacketsInID == id) { // nope! bump and wrap the counter, then return mPacketsInID++; diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index ccefdb56c..0f46d2810 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -202,8 +202,8 @@ void LLCurl::Responder::completedHeader(U32 status, const std::string& reason, c } -namespace boost -{ +//namespace boost +//{ void intrusive_ptr_add_ref(LLCurl::Responder* p) { ++p->mReferenceCount; @@ -216,7 +216,7 @@ namespace boost delete p; } } -}; +//}; ////////////////////////////////////////////////////////////////////////////// @@ -309,6 +309,14 @@ LLCurl::Easy* LLCurl::Easy::getEasy() CURLcode result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); check_curl_code(result); + // Disable SSL/TLS session caching. Some servers refuse to talk to us when session ids are enabled. + // id.secondlife.com is such a server, when greeted with a SSL HELLO and a session id, it immediatly returns a RST packet and closes + // the connections. + // Fixes: FIRE-5368, FIRE-5756, VWR-28039, VWR-28629 + result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_SSL_SESSIONID_CACHE, 0); + check_curl_code(result); + + ++gCurlEasyCount; return easy; } @@ -758,7 +766,7 @@ bool LLCurl::Multi::doPerform() } mQueued = q; - setState(STATE_COMPLETED) ; + setState(STATE_COMPLETED) ; mIdleTimer.reset() ; } else if(!mValid && mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it. diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 1609530a3..fa8465bfe 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -378,11 +378,11 @@ private: void cleanupMulti(LLCurl::Multi* multi) ; } ; -namespace boost -{ +//namespace boost +//{ void intrusive_ptr_add_ref(LLCurl::Responder* p); void intrusive_ptr_release(LLCurl::Responder* p); -}; +//}; class LLCurlRequest diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp deleted file mode 100644 index 612d76596..000000000 --- a/indra/llmessage/llhttpassetstorage.cpp +++ /dev/null @@ -1,1459 +0,0 @@ -/** - * @file llhttpassetstorage.cpp - * @brief Subclass capable of loading asset data to/from an external - * source. Currently, a web server accessed via curl - * - * $LicenseInfo:firstyear=2003&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llhttpassetstorage.h" - -#include - -#include "indra_constants.h" -#include "message.h" -#include "llproxy.h" -#include "llvfile.h" -#include "llvfs.h" - -#ifdef LL_STANDALONE -# include -#else -# include "zlib/zlib.h" -#endif - -const U32 MAX_RUNNING_REQUESTS = 1; -const F32 MAX_PROCESSING_TIME = 0.005f; -const S32 CURL_XFER_BUFFER_SIZE = 65536; -// Try for 30 minutes for now. -const F32 GET_URL_TO_FILE_TIMEOUT = 1800.0f; - -const S32 COMPRESSED_INPUT_BUFFER_SIZE = 4096; - -const S32 HTTP_OK = 200; -const S32 HTTP_PUT_OK = 201; -const S32 HTTP_NO_CONTENT = 204; -const S32 HTTP_MISSING = 404; -const S32 HTTP_SERVER_BAD_GATEWAY = 502; -const S32 HTTP_SERVER_TEMP_UNAVAILABLE = 503; - -///////////////////////////////////////////////////////////////////////////////// -// LLTempAssetData -// An asset not stored on central asset store, but on a simulator node somewhere. -///////////////////////////////////////////////////////////////////////////////// -struct LLTempAssetData -{ - LLUUID mAssetID; - LLUUID mAgentID; - std::string mHostName; -}; - -///////////////////////////////////////////////////////////////////////////////// -// LLHTTPAssetRequest -///////////////////////////////////////////////////////////////////////////////// - -class LLHTTPAssetRequest : public LLAssetRequest -{ -public: - LLHTTPAssetRequest(LLHTTPAssetStorage *asp, const LLUUID &uuid, - LLAssetType::EType type, LLAssetStorage::ERequestType rt, - const std::string& url, CURLM *curl_multi); - virtual ~LLHTTPAssetRequest(); - - void setupCurlHandle(); - void cleanupCurlHandle(); - - void prepareCompressedUpload(); - void finishCompressedUpload(); - size_t readCompressedData(void* data, size_t size); - - static size_t curlCompressedUploadCallback( - void *data, size_t size, size_t nmemb, void *user_data); - - virtual LLSD getTerseDetails() const; - virtual LLSD getFullDetails() const; - -public: - LLHTTPAssetStorage *mAssetStoragep; - - CURL *mCurlHandle; - CURLM *mCurlMultiHandle; - std::string mURLBuffer; - struct curl_slist *mHTTPHeaders; - LLVFile *mVFile; - LLUUID mTmpUUID; - LLAssetStorage::ERequestType mRequestType; - - bool mZInitialized; - z_stream mZStream; - char* mZInputBuffer; - bool mZInputExhausted; - - FILE *mFP; -}; - - -LLHTTPAssetRequest::LLHTTPAssetRequest(LLHTTPAssetStorage *asp, - const LLUUID &uuid, - LLAssetType::EType type, - LLAssetStorage::ERequestType rt, - const std::string& url, - CURLM *curl_multi) - : LLAssetRequest(uuid, type), - mZInitialized(false) -{ - memset(&mZStream, 0, sizeof(mZStream)); // we'll initialize this later, but for now zero the whole C-style struct to avoid debug/coverity noise - mAssetStoragep = asp; - mCurlHandle = NULL; - mCurlMultiHandle = curl_multi; - mVFile = NULL; - mRequestType = rt; - mHTTPHeaders = NULL; - mFP = NULL; - mZInputBuffer = NULL; - mZInputExhausted = false; - - mURLBuffer = url; -} - -LLHTTPAssetRequest::~LLHTTPAssetRequest() -{ - // Cleanup/cancel the request - if (mCurlHandle) - { - curl_multi_remove_handle(mCurlMultiHandle, mCurlHandle); - cleanupCurlHandle(); - } - if (mHTTPHeaders) - { - curl_slist_free_all(mHTTPHeaders); - } - delete mVFile; - finishCompressedUpload(); -} - -// virtual -LLSD LLHTTPAssetRequest::getTerseDetails() const -{ - LLSD sd = LLAssetRequest::getTerseDetails(); - - sd["url"] = mURLBuffer; - - return sd; -} - -// virtual -LLSD LLHTTPAssetRequest::getFullDetails() const -{ - LLSD sd = LLAssetRequest::getFullDetails(); - - if (mCurlHandle) - { - long curl_response = -1; - long curl_connect = -1; - double curl_total_time = -1.0f; - double curl_size_upload = -1.0f; - double curl_size_download = -1.0f; - double curl_content_length_upload = -1.0f; - double curl_content_length_download = -1.0f; - long curl_request_size = -1; - const char* curl_content_type = NULL; - - curl_easy_getinfo(mCurlHandle, CURLINFO_HTTP_CODE, &curl_response); - curl_easy_getinfo(mCurlHandle, CURLINFO_HTTP_CONNECTCODE, &curl_connect); - curl_easy_getinfo(mCurlHandle, CURLINFO_TOTAL_TIME, &curl_total_time); - curl_easy_getinfo(mCurlHandle, CURLINFO_SIZE_UPLOAD, &curl_size_upload); - curl_easy_getinfo(mCurlHandle, CURLINFO_SIZE_DOWNLOAD, &curl_size_download); - curl_easy_getinfo(mCurlHandle, CURLINFO_CONTENT_LENGTH_UPLOAD, &curl_content_length_upload); - curl_easy_getinfo(mCurlHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &curl_content_length_download); - curl_easy_getinfo(mCurlHandle, CURLINFO_REQUEST_SIZE, &curl_request_size); - curl_easy_getinfo(mCurlHandle, CURLINFO_CONTENT_TYPE, &curl_content_type); - - sd["curl_response_code"] = (int) curl_response; - sd["curl_http_connect_code"] = (int) curl_connect; - sd["curl_total_time"] = curl_total_time; - sd["curl_size_upload"] = curl_size_upload; - sd["curl_size_download"] = curl_size_download; - sd["curl_content_length_upload"] = curl_content_length_upload; - sd["curl_content_length_download"] = curl_content_length_download; - sd["curl_request_size"] = (int) curl_request_size; - if (curl_content_type) - { - sd["curl_content_type"] = curl_content_type; - } - else - { - sd["curl_content_type"] = ""; - } - } - - sd["temp_id"] = mTmpUUID; - sd["request_type"] = LLAssetStorage::getRequestName(mRequestType); - sd["z_initialized"] = mZInitialized; - sd["z_input_exhausted"] = mZInputExhausted; - - S32 file_size = -1; - if (mFP) - { - struct stat file_stat; - int file_desc = fileno(mFP); - if ( fstat(file_desc, &file_stat) == 0) - { - file_size = file_stat.st_size; - } - } - sd["file_size"] = file_size; - - return sd; -} - - -void LLHTTPAssetRequest::setupCurlHandle() -{ - // *NOTE: Similar code exists in mapserver/llcurlutil.cpp JC - mCurlHandle = LLCurl::newEasyHandle(); - llassert_always(mCurlHandle != NULL) ; - - // Apply proxy settings if configured to do so - LLProxy::getInstance()->applyProxySettings(mCurlHandle); - - curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1); - curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1); - curl_easy_setopt(mCurlHandle, CURLOPT_URL, mURLBuffer.c_str()); - curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this); - if (LLAssetStorage::RT_DOWNLOAD == mRequestType) - { - curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, ""); - // only do this on downloads, as uploads - // to some apache configs (like our test grids) - // mistakenly claim the response is gzip'd if the resource - // name ends in .gz, even though in a PUT, the response is - // just plain HTML saying "created" - } - /* Remove the Pragma: no-cache header that libcurl inserts by default; - we want the cached version, if possible. */ - if (mZInitialized) - { - curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, ""); - // disable use of proxy, which can't handle chunked transfers - } - mHTTPHeaders = curl_slist_append(mHTTPHeaders, "Pragma:"); - - // bug in curl causes DNS to be cached for too long a time, 0 sets it to never cache DNS results internally (to curl) - curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); - - // resist the temptation to explicitly add the Transfer-Encoding: chunked - // header here - invokes a libCURL bug - curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mHTTPHeaders); - if (mAssetStoragep) - { - // Set the appropriate pending upload or download flag - mAssetStoragep->addRunningRequest(mRequestType, this); - } - else - { - llerrs << "LLHTTPAssetRequest::setupCurlHandle - No asset storage associated with this request!" << llendl; - } -} - -void LLHTTPAssetRequest::cleanupCurlHandle() -{ - LLCurl::deleteEasyHandle(mCurlHandle); - if (mAssetStoragep) - { - // Terminating a request. Thus upload or download is no longer pending. - mAssetStoragep->removeRunningRequest(mRequestType, this); - } - else - { - llerrs << "LLHTTPAssetRequest::~LLHTTPAssetRequest - No asset storage associated with this request!" << llendl; - } - mCurlHandle = NULL; -} - -void LLHTTPAssetRequest::prepareCompressedUpload() -{ - mZStream.next_in = Z_NULL; - mZStream.avail_in = 0; - mZStream.zalloc = Z_NULL; - mZStream.zfree = Z_NULL; - mZStream.opaque = Z_NULL; - - int r = deflateInit2(&mZStream, - 1, // compression level - Z_DEFLATED, // the only method defined - 15 + 16, // the default windowBits + gzip header flag - 8, // the default memLevel - Z_DEFAULT_STRATEGY); - - if (r != Z_OK) - { - llerrs << "LLHTTPAssetRequest::prepareCompressedUpload defalateInit2() failed" << llendl; - } - - mZInitialized = true; - mZInputBuffer = new char[COMPRESSED_INPUT_BUFFER_SIZE]; - mZInputExhausted = false; - - mVFile = new LLVFile(gAssetStorage->mVFS, - getUUID(), getType(), LLVFile::READ); -} - -void LLHTTPAssetRequest::finishCompressedUpload() -{ - if (mZInitialized) - { - llinfos << "LLHTTPAssetRequest::finishCompressedUpload: " - << "read " << mZStream.total_in << " byte asset file, " - << "uploaded " << mZStream.total_out << " byte compressed asset" - << llendl; - - deflateEnd(&mZStream); - delete[] mZInputBuffer; - } -} - -size_t LLHTTPAssetRequest::readCompressedData(void* data, size_t size) -{ - llassert(mZInitialized); - - mZStream.next_out = (Bytef*)data; - mZStream.avail_out = size; - - while (mZStream.avail_out > 0) - { - if (mZStream.avail_in == 0 && !mZInputExhausted) - { - S32 to_read = llmin(COMPRESSED_INPUT_BUFFER_SIZE, - (S32)(mVFile->getSize() - mVFile->tell())); - - if ( to_read > 0 ) - { - mVFile->read((U8*)mZInputBuffer, to_read); /*Flawfinder: ignore*/ - mZStream.next_in = (Bytef*)mZInputBuffer; - mZStream.avail_in = mVFile->getLastBytesRead(); - } - - mZInputExhausted = mZStream.avail_in == 0; - } - - int r = deflate(&mZStream, - mZInputExhausted ? Z_FINISH : Z_NO_FLUSH); - - if (r == Z_STREAM_END || r < 0 || mZInputExhausted) - { - if (r < 0) - { - llwarns << "LLHTTPAssetRequest::readCompressedData: deflate returned error code " - << (S32) r << llendl; - } - break; - } - } - - return size - mZStream.avail_out; -} - -//static -size_t LLHTTPAssetRequest::curlCompressedUploadCallback( - void *data, size_t size, size_t nmemb, void *user_data) -{ - size_t num_read = 0; - - if (gAssetStorage) - { - CURL *curl_handle = (CURL *)user_data; - LLHTTPAssetRequest *req = NULL; - curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &req); - if (req) - { - num_read = req->readCompressedData(data, size * nmemb); - } - } - - return num_read; -} - -///////////////////////////////////////////////////////////////////////////////// -// LLHTTPAssetStorage -///////////////////////////////////////////////////////////////////////////////// - - -LLHTTPAssetStorage::LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, - LLVFS *vfs, LLVFS *static_vfs, - const LLHost &upstream_host, - const std::string& web_host, - const std::string& local_web_host, - const std::string& host_name) - : LLAssetStorage(msg, xfer, vfs, static_vfs, upstream_host) -{ - _init(web_host, local_web_host, host_name); -} - -LLHTTPAssetStorage::LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, - LLVFS *vfs, - LLVFS *static_vfs, - const std::string& web_host, - const std::string& local_web_host, - const std::string& host_name) - : LLAssetStorage(msg, xfer, vfs, static_vfs) -{ - _init(web_host, local_web_host, host_name); -} - -void LLHTTPAssetStorage::_init(const std::string& web_host, const std::string& local_web_host, const std::string& host_name) -{ - mBaseURL = web_host; - mLocalBaseURL = local_web_host; - mHostName = host_name; - - // curl_global_init moved to LLCurl::initClass() - - mCurlMultiHandle = LLCurl::newMultiHandle() ; - llassert_always(mCurlMultiHandle != NULL) ; -} - -LLHTTPAssetStorage::~LLHTTPAssetStorage() -{ - LLCurl::deleteMultiHandle(mCurlMultiHandle); - mCurlMultiHandle = NULL; - - // curl_global_cleanup moved to LLCurl::initClass() -} - -// storing data is simpler than getting it, so we just overload the whole method -void LLHTTPAssetStorage::storeAssetData( - const LLUUID& uuid, - LLAssetType::EType type, - LLAssetStorage::LLStoreAssetCallback callback, - void* user_data, - bool temp_file, - bool is_priority, - bool store_local, - const LLUUID& requesting_agent_id, - bool user_waiting, - F64 timeout) -{ - if (mVFS->getExists(uuid, type)) // VFS treats nonexistant and zero-length identically - { - LLAssetRequest *req = new LLAssetRequest(uuid, type); - req->mUpCallback = callback; - req->mUserData = user_data; - req->mRequestingAgentID = requesting_agent_id; - req->mIsUserWaiting = user_waiting; - req->mTimeout = timeout; - - // LLAssetStorage metric: Successful Request - S32 size = mVFS->getSize(uuid, type); - const char *message; - if( store_local ) - { - message = "Added to local upload queue"; - } - else - { - message = "Added to upload queue"; - } - reportMetric( uuid, type, LLStringUtil::null, requesting_agent_id, size, MR_OKAY, __FILE__, __LINE__, message ); - - // this will get picked up and transmitted in checkForTimeouts - if(store_local) - { - mPendingLocalUploads.push_back(req); - } - else if(is_priority) - { - mPendingUploads.push_front(req); - } - else - { - mPendingUploads.push_back(req); - } - } - else - { - llwarns << "AssetStorage: attempt to upload non-existent vfile " << uuid << ":" << LLAssetType::lookup(type) << llendl; - if (callback) - { - // LLAssetStorage metric: Zero size VFS - reportMetric( uuid, type, LLStringUtil::null, requesting_agent_id, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" ); - callback(uuid, user_data, LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE, LL_EXSTAT_NONEXISTENT_FILE); - } - } -} - -// virtual -void LLHTTPAssetStorage::storeAssetData( - const std::string& filename, - const LLUUID& asset_id, - LLAssetType::EType asset_type, - LLStoreAssetCallback callback, - void* user_data, - bool temp_file, - bool is_priority, - bool user_waiting, - F64 timeout) -{ - llinfos << "LLAssetStorage::storeAssetData (legacy)" << asset_id << ":" << LLAssetType::lookup(asset_type) << llendl; - - LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest; - - legacy->mUpCallback = callback; - legacy->mUserData = user_data; - - FILE *fp = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ - S32 size = 0; - if (fp) - { - fseek(fp, 0, SEEK_END); - size = ftell(fp); - fseek(fp, 0, SEEK_SET); - } - - if( size ) - { - LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE); - - file.setMaxSize(size); - - const S32 buf_size = 65536; - U8 copy_buf[buf_size]; - while ((size = (S32)fread(copy_buf, 1, buf_size, fp))) - { - file.write(copy_buf, size); - } - fclose(fp); - - // if this upload fails, the caller needs to setup a new tempfile for us - if (temp_file) - { - LLFile::remove(filename); - } - - // LLAssetStorage metric: Success not needed; handled in the overloaded method here: - storeAssetData( - asset_id, - asset_type, - legacyStoreDataCallback, - (void**)legacy, - temp_file, - is_priority, - false, - LLUUID::null, - user_waiting, - timeout); - } - else // !size - { - if( fp ) - { - // LLAssetStorage metric: Zero size - reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file was zero length" ); - fclose( fp ); - } - else - { - // LLAssetStorage metric: Missing File - reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_FILE_NONEXIST, __FILE__, __LINE__, "The file didn't exist" ); - } - if (callback) - { - callback(LLUUID::null, user_data, LL_ERR_CANNOT_OPEN_FILE, LL_EXSTAT_BLOCKED_FILE); - } - delete legacy; - } -} - -// virtual -LLSD LLHTTPAssetStorage::getPendingDetails(LLAssetStorage::ERequestType rt, - LLAssetType::EType asset_type, - const std::string& detail_prefix) const -{ - LLSD sd = LLAssetStorage::getPendingDetails(rt, asset_type, detail_prefix); - const request_list_t* running = getRunningList(rt); - if (running) - { - // Loop through the pending requests sd, and add extra info about its running status. - S32 num_pending = sd["requests"].size(); - S32 i; - for (i = 0; i < num_pending; ++i) - { - LLSD& pending = sd["requests"][i]; - // See if this pending request is running. - const LLAssetRequest* req = findRequest(running, - LLAssetType::lookup(pending["type"].asString()), - pending["asset_id"]); - if (req) - { - // Keep the detail_url so we don't have to rebuild it. - LLURI detail_url = pending["detail"]; - pending = req->getTerseDetails(); - pending["detail"] = detail_url; - pending["is_running"] = true; - } - else - { - pending["is_running"] = false; - } - } - } - return sd; -} - -// virtual -LLSD LLHTTPAssetStorage::getPendingRequest(LLAssetStorage::ERequestType rt, - LLAssetType::EType asset_type, - const LLUUID& asset_id) const -{ - // Look for this asset in the running list first. - const request_list_t* running = getRunningList(rt); - if (running) - { - LLSD sd = LLAssetStorage::getPendingRequestImpl(running, asset_type, asset_id); - if (sd) - { - sd["is_running"] = true; - return sd; - } - } - LLSD sd = LLAssetStorage::getPendingRequest(rt, asset_type, asset_id); - if (sd) - { - sd["is_running"] = false; - } - return sd; -} - -// virtual -bool LLHTTPAssetStorage::deletePendingRequest(LLAssetStorage::ERequestType rt, - LLAssetType::EType asset_type, - const LLUUID& asset_id) -{ - // Try removing this from the running list first. - request_list_t* running = getRunningList(rt); - if (running) - { - LLAssetRequest* req = findRequest(running, asset_type, asset_id); - if (req) - { - // Remove this request from the running list to get it out of curl. - running->remove(req); - - // Find this request in the pending list, so we can move it to the end of the line. - request_list_t* pending = getRequestList(rt); - if (pending) - { - request_list_t::iterator result = std::find_if(pending->begin(), pending->end(), - std::bind2nd(ll_asset_request_equal(), req)); - if (pending->end() != result) - { - // This request was found in the pending list. Move it to the end! - LLAssetRequest* pending_req = *result; - pending->remove(pending_req); - - if (!pending_req->mIsUserWaiting) //A user is waiting on this request. Toss it. - { - pending->push_back(pending_req); - } - else - { - if (pending_req->mUpCallback) //Clean up here rather than _callUploadCallbacks because this request is already cleared the req. - { - pending_req->mUpCallback(pending_req->getUUID(), pending_req->mUserData, -1, LL_EXSTAT_REQUEST_DROPPED); - } - - } - - llinfos << "Asset " << getRequestName(rt) << " request for " - << asset_id << "." << LLAssetType::lookup(asset_type) - << " removed from curl and placed at the end of the pending queue." - << llendl; - } - else - { - llwarns << "Unable to find pending " << getRequestName(rt) << " request for " - << asset_id << "." << LLAssetType::lookup(asset_type) << llendl; - } - } - delete req; - - return true; - } - } - return LLAssetStorage::deletePendingRequest(rt, asset_type, asset_id); -} - -// internal requester, used by getAssetData in superclass -void LLHTTPAssetStorage::_queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, - void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat), - void *user_data, BOOL duplicate, - BOOL is_priority) -{ - // stash the callback info so we can find it after we get the response message - LLAssetRequest *req = new LLAssetRequest(uuid, type); - req->mDownCallback = callback; - req->mUserData = user_data; - req->mIsPriority = is_priority; - - // this will get picked up and downloaded in checkForTimeouts - - // - // HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK! Asset requests were taking too long and timing out. - // Since texture requests are the LEAST sensitive (on the simulator) to being delayed, add - // non-texture requests to the front, and add texture requests to the back. The theory is - // that we always want them first, even if they're out of order. - // - - if (req->getType() == LLAssetType::AT_TEXTURE) - { - mPendingDownloads.push_back(req); - } - else - { - mPendingDownloads.push_front(req); - } -} - -LLAssetRequest* LLHTTPAssetStorage::findNextRequest(LLAssetStorage::request_list_t& pending, - LLAssetStorage::request_list_t& running) -{ - // Early exit if the running list is full, or we don't have more pending than running. - if (running.size() >= MAX_RUNNING_REQUESTS - || pending.size() <= running.size()) return NULL; - - // Look for the first pending request that is not already running. - request_list_t::iterator running_begin = running.begin(); - request_list_t::iterator running_end = running.end(); - - request_list_t::iterator pending_iter = pending.begin(); - request_list_t::iterator pending_end = pending.end(); - // Loop over all pending requests until we miss finding it in the running list. - for (; pending_iter != pending.end(); ++pending_iter) - { - LLAssetRequest* req = *pending_iter; - // Look for this pending request in the running list. - if (running_end == std::find_if(running_begin, running_end, - std::bind2nd(ll_asset_request_equal(), req))) - { - // It isn't running! Return it. - return req; - } - } - return NULL; -} - -// overloaded to additionally move data to/from the webserver -void LLHTTPAssetStorage::checkForTimeouts() -{ - CURLMcode mcode; - LLAssetRequest *req; - while ( (req = findNextRequest(mPendingDownloads, mRunningDownloads)) ) - { - // Setup this curl download request - // We need to generate a new request here - // since the one in the list could go away - std::string tmp_url; - std::string uuid_str; - req->getUUID().toString(uuid_str); - std::string base_url = getBaseURL(req->getUUID(), req->getType()); - tmp_url = llformat("%s/%36s.%s", base_url.c_str() , uuid_str.c_str(), LLAssetType::lookup(req->getType())); - - LLHTTPAssetRequest *new_req = new LLHTTPAssetRequest(this, req->getUUID(), - req->getType(), RT_DOWNLOAD, tmp_url, mCurlMultiHandle); - new_req->mTmpUUID.generate(); - - // Sets pending download flag internally - new_req->setupCurlHandle(); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_FOLLOWLOCATION, TRUE); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEFUNCTION, &curlDownCallback); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEDATA, new_req->mCurlHandle); - - mcode = curl_multi_add_handle(mCurlMultiHandle, new_req->mCurlHandle); - if (mcode > CURLM_OK) - { - // Failure. Deleting the pending request will remove it from the running - // queue, and push it to the end of the pending queue. - new_req->cleanupCurlHandle(); - deletePendingRequest(RT_DOWNLOAD, new_req->getType(), new_req->getUUID()); - break; - } - else - { - llinfos << "Requesting " << new_req->mURLBuffer << llendl; - } - } - - while ( (req = findNextRequest(mPendingUploads, mRunningUploads)) ) - { - // setup this curl upload request - - bool do_compress = req->getType() == LLAssetType::AT_OBJECT; - - std::string tmp_url; - std::string uuid_str; - req->getUUID().toString(uuid_str); - tmp_url = mBaseURL + "/" + uuid_str + "." + LLAssetType::lookup(req->getType()); - if (do_compress) tmp_url += ".gz"; - - LLHTTPAssetRequest *new_req = new LLHTTPAssetRequest(this, req->getUUID(), - req->getType(), RT_UPLOAD, tmp_url, mCurlMultiHandle); - - if (req->mIsUserWaiting) //If a user is waiting on a realtime response, we want to perserve information across upload attempts. - { - new_req->mTime = req->mTime; - new_req->mTimeout = req->mTimeout; - new_req->mIsUserWaiting = req->mIsUserWaiting; - } - - if (do_compress) - { - new_req->prepareCompressedUpload(); - } - - // Sets pending upload flag internally - new_req->setupCurlHandle(); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_UPLOAD, 1); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEFUNCTION, &nullOutputCallback); - - if (do_compress) - { - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READFUNCTION, - &LLHTTPAssetRequest::curlCompressedUploadCallback); - } - else - { - LLVFile file(mVFS, req->getUUID(), req->getType()); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_INFILESIZE, file.getSize()); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READFUNCTION, - &curlUpCallback); - } - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READDATA, new_req->mCurlHandle); - - mcode = curl_multi_add_handle(mCurlMultiHandle, new_req->mCurlHandle); - if (mcode > CURLM_OK) - { - // Failure. Deleting the pending request will remove it from the running - // queue, and push it to the end of the pending queue. - new_req->cleanupCurlHandle(); - deletePendingRequest(RT_UPLOAD, new_req->getType(), new_req->getUUID()); - break; - } - else - { - // Get the uncompressed file size. - LLVFile file(mVFS,new_req->getUUID(),new_req->getType()); - S32 size = file.getSize(); - llinfos << "Requesting PUT " << new_req->mURLBuffer << ", asset size: " << size << " bytes" << llendl; - if (size == 0) - { - llwarns << "Rejecting zero size PUT request!" << llendl; - new_req->cleanupCurlHandle(); - deletePendingRequest(RT_UPLOAD, new_req->getType(), new_req->getUUID()); - } - } - // Pending upload will have been flagged by the request - } - - while ( (req = findNextRequest(mPendingLocalUploads, mRunningLocalUploads)) ) - { - // setup this curl upload request - LLVFile file(mVFS, req->getUUID(), req->getType()); - - std::string tmp_url; - std::string uuid_str; - req->getUUID().toString(uuid_str); - - // KLW - All temporary uploads are saved locally "http://localhost:12041/asset" - tmp_url = llformat("%s/%36s.%s", mLocalBaseURL.c_str(), uuid_str.c_str(), LLAssetType::lookup(req->getType())); - - LLHTTPAssetRequest *new_req = new LLHTTPAssetRequest(this, req->getUUID(), - req->getType(), RT_LOCALUPLOAD, tmp_url, mCurlMultiHandle); - new_req->mRequestingAgentID = req->mRequestingAgentID; - - // Sets pending upload flag internally - new_req->setupCurlHandle(); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_PUT, 1); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_INFILESIZE, file.getSize()); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEFUNCTION, &nullOutputCallback); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READFUNCTION, &curlUpCallback); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READDATA, new_req->mCurlHandle); - - mcode = curl_multi_add_handle(mCurlMultiHandle, new_req->mCurlHandle); - if (mcode > CURLM_OK) - { - // Failure. Deleting the pending request will remove it from the running - // queue, and push it to the end of the pending queue. - new_req->cleanupCurlHandle(); - deletePendingRequest(RT_LOCALUPLOAD, new_req->getType(), new_req->getUUID()); - break; - } - else - { - // Get the uncompressed file size. - S32 size = file.getSize(); - - llinfos << "TAT: LLHTTPAssetStorage::checkForTimeouts() : pending local!" - << " Requesting PUT " << new_req->mURLBuffer << ", asset size: " << size << " bytes" << llendl; - if (size == 0) - { - - llwarns << "Rejecting zero size PUT request!" << llendl; - new_req->cleanupCurlHandle(); - deletePendingRequest(RT_UPLOAD, new_req->getType(), new_req->getUUID()); - } - - } - // Pending upload will have been flagged by the request - } - S32 count = 0; - int queue_length; - do - { - mcode = curl_multi_perform(mCurlMultiHandle, &queue_length); - count++; - } while (mcode == CURLM_CALL_MULTI_PERFORM && (count < 5)); - - CURLMsg *curl_msg; - do - { - curl_msg = curl_multi_info_read(mCurlMultiHandle, &queue_length); - if (curl_msg && curl_msg->msg == CURLMSG_DONE) - { - long curl_result = 0; - S32 xfer_result = LL_ERR_NOERR; - - LLHTTPAssetRequest *req = NULL; - curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_PRIVATE, &req); - - // TODO: Throw curl_result at all callbacks. - curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_HTTP_CODE, &curl_result); - if (RT_UPLOAD == req->mRequestType || RT_LOCALUPLOAD == req->mRequestType) - { - if (curl_msg->data.result == CURLE_OK && - ( curl_result == HTTP_OK - || curl_result == HTTP_PUT_OK - || curl_result == HTTP_NO_CONTENT)) - { - llinfos << "Success uploading " << req->getUUID() << " to " << req->mURLBuffer << llendl; - if (RT_LOCALUPLOAD == req->mRequestType) - { - addTempAssetData(req->getUUID(), req->mRequestingAgentID, mHostName); - } - } - else if (curl_msg->data.result == CURLE_COULDNT_CONNECT || - curl_msg->data.result == CURLE_OPERATION_TIMEOUTED || - curl_result == HTTP_SERVER_BAD_GATEWAY || - curl_result == HTTP_SERVER_TEMP_UNAVAILABLE) - { - llwarns << "Re-requesting upload for " << req->getUUID() << ". Received upload error to " << req->mURLBuffer << - " with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl; - - ////HACK (probably) I am sick of this getting requeued and driving me mad. - //if (req->mIsUserWaiting) - //{ - // deletePendingRequest(RT_UPLOAD, req->getType(), req->getUUID()); - //} - } - else - { - llwarns << "Failure uploading " << req->getUUID() << " to " << req->mURLBuffer << - " with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl; - - xfer_result = LL_ERR_ASSET_REQUEST_FAILED; - } - - if (!(curl_msg->data.result == CURLE_COULDNT_CONNECT || - curl_msg->data.result == CURLE_OPERATION_TIMEOUTED || - curl_result == HTTP_SERVER_BAD_GATEWAY || - curl_result == HTTP_SERVER_TEMP_UNAVAILABLE)) - { - // shared upload finished callback - // in the base class, this is called from processUploadComplete - _callUploadCallbacks(req->getUUID(), req->getType(), (xfer_result == 0), LL_EXSTAT_CURL_RESULT | curl_result); - // Pending upload flag will get cleared when the request is deleted - } - } - else if (RT_DOWNLOAD == req->mRequestType) - { - if (curl_result == HTTP_OK && curl_msg->data.result == CURLE_OK) - { - if (req->mVFile && req->mVFile->getSize() > 0) - { - llinfos << "Success downloading " << req->mURLBuffer << ", size " << req->mVFile->getSize() << llendl; - - req->mVFile->rename(req->getUUID(), req->getType()); - } - else - { - // *TODO: if this actually indicates a bad asset on the server - // (not certain at this point), then delete it - llwarns << "Found " << req->mURLBuffer << " to be zero size" << llendl; - xfer_result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE; - } - } - else - { - // KLW - TAT See if an avatar owns this texture, and if so request re-upload. - llwarns << "Failure downloading " << req->mURLBuffer << - " with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl; - - xfer_result = (curl_result == HTTP_MISSING) ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED; - - if (req->mVFile) - { - req->mVFile->remove(); - } - } - - // call the static callback for transfer completion - // this will cleanup all requests for this asset, including ours - downloadCompleteCallback( - xfer_result, - req->getUUID(), - req->getType(), - (void *)req, - LL_EXSTAT_CURL_RESULT | curl_result); - // Pending download flag will get cleared when the request is deleted - } - else - { - // nothing, just axe this request - // currently this can only mean an asset delete - } - - // Deleting clears the pending upload/download flag if it's set and the request is transferring - delete req; - req = NULL; - } - - } while (curl_msg && queue_length > 0); - - - // Cleanup - // We want to bump to the back of the line any running uploads that have timed out. - bumpTimedOutUploads(); - - LLAssetStorage::checkForTimeouts(); -} - -void LLHTTPAssetStorage::bumpTimedOutUploads() -{ - bool user_waiting=FALSE; - - F64 mt_secs = LLMessageSystem::getMessageTimeSeconds(); - - if (mPendingUploads.size()) - { - request_list_t::iterator it = mPendingUploads.begin(); - LLAssetRequest* req = *it; - user_waiting=req->mIsUserWaiting; - } - - // No point bumping currently running uploads if there are no others in line. - if (!(mPendingUploads.size() > mRunningUploads.size()) && !user_waiting) - { - return; - } - - // deletePendingRequest will modify the mRunningUploads list so we don't want to iterate over it. - request_list_t temp_running = mRunningUploads; - - request_list_t::iterator it = temp_running.begin(); - request_list_t::iterator end = temp_running.end(); - for ( ; it != end; ++it) - { - //request_list_t::iterator curiter = iter++; - LLAssetRequest* req = *it; - - if ( req->mTimeout < (mt_secs - req->mTime) ) - { - llwarns << "Asset upload request timed out for " - << req->getUUID() << "." - << LLAssetType::lookup(req->getType()) - << ", bumping to the back of the line!" << llendl; - - deletePendingRequest(RT_UPLOAD, req->getType(), req->getUUID()); - } - } -} - -// static -size_t LLHTTPAssetStorage::curlDownCallback(void *data, size_t size, size_t nmemb, void *user_data) -{ - if (!gAssetStorage) - { - llwarns << "Missing gAssetStorage, aborting curl download callback!" << llendl; - return 0; - } - S32 bytes = (S32)(size * nmemb); - CURL *curl_handle = (CURL *)user_data; - LLHTTPAssetRequest *req = NULL; - curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &req); - - if (! req->mVFile) - { - req->mVFile = new LLVFile(gAssetStorage->mVFS, req->mTmpUUID, LLAssetType::AT_NONE, LLVFile::APPEND); - } - - double content_length = 0.0; - curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &content_length); - - // sanitize content_length, reconcile w/ actual data - S32 file_length = llmax(0, (S32)llmin(content_length, 20000000.0), bytes + req->mVFile->getSize()); - - req->mVFile->setMaxSize(file_length); - req->mVFile->write((U8*)data, bytes); - - return nmemb; -} - -// static -size_t LLHTTPAssetStorage::curlUpCallback(void *data, size_t size, size_t nmemb, void *user_data) -{ - if (!gAssetStorage) - { - llwarns << "Missing gAssetStorage, aborting curl download callback!" << llendl; - return 0; - } - CURL *curl_handle = (CURL *)user_data; - LLHTTPAssetRequest *req = NULL; - curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &req); - - if (! req->mVFile) - { - req->mVFile = new LLVFile(gAssetStorage->mVFS, req->getUUID(), req->getType(), LLVFile::READ); - } - - S32 bytes = llmin((S32)(size * nmemb), (S32)(req->mVFile->getSize() - req->mVFile->tell())); - - req->mVFile->read((U8*)data, bytes);/*Flawfinder: ignore*/ - - return req->mVFile->getLastBytesRead(); -} - -// static -size_t LLHTTPAssetStorage::nullOutputCallback(void *data, size_t size, size_t nmemb, void *user_data) -{ - // do nothing, this is here to soak up script output so it doesn't end up on stdout - - return nmemb; -} - - - -// blocking asset fetch which bypasses the VFS -// this is a very limited function for use by the simstate loader and other one-offs -S32 LLHTTPAssetStorage::getURLToFile(const LLUUID& uuid, LLAssetType::EType asset_type, const std::string &url, const std::string& filename, progress_callback callback, void *userdata) -{ - // *NOTE: There is no guarantee that the uuid and the asset_type match - // - not that it matters. - Doug - lldebugs << "LLHTTPAssetStorage::getURLToFile() - " << url << llendl; - - FILE *fp = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/ - if (! fp) - { - llwarns << "Failed to open " << filename << " for writing" << llendl; - return LL_ERR_ASSET_REQUEST_FAILED; - } - - // make sure we use the normal curl setup, even though we don't really need a request object - LLHTTPAssetRequest req(this, uuid, asset_type, RT_DOWNLOAD, url, mCurlMultiHandle); - req.mFP = fp; - - req.setupCurlHandle(); - curl_easy_setopt(req.mCurlHandle, CURLOPT_FOLLOWLOCATION, TRUE); - curl_easy_setopt(req.mCurlHandle, CURLOPT_WRITEFUNCTION, &curlFileDownCallback); - curl_easy_setopt(req.mCurlHandle, CURLOPT_WRITEDATA, req.mCurlHandle); - - curl_multi_add_handle(mCurlMultiHandle, req.mCurlHandle); - llinfos << "Requesting as file " << req.mURLBuffer << llendl; - - // braindead curl loop - int queue_length; - CURLMsg *curl_msg; - LLTimer timeout; - timeout.setTimerExpirySec(GET_URL_TO_FILE_TIMEOUT); - bool success = false; - S32 xfer_result = 0; - do - { - curl_multi_perform(mCurlMultiHandle, &queue_length); - curl_msg = curl_multi_info_read(mCurlMultiHandle, &queue_length); - - if (callback) - { - callback(userdata); - } - - if ( curl_msg && (CURLMSG_DONE == curl_msg->msg) ) - { - success = true; - } - else if (timeout.hasExpired()) - { - llwarns << "Request for " << url << " has timed out." << llendl; - success = false; - xfer_result = LL_ERR_ASSET_REQUEST_FAILED; - break; - } - } while (!success); - - if (success) - { - long curl_result = 0; - curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_HTTP_CODE, &curl_result); - - if (curl_result == HTTP_OK && curl_msg->data.result == CURLE_OK) - { - S32 size = ftell(req.mFP); - if (size > 0) - { - // everything seems to be in order - llinfos << "Success downloading " << req.mURLBuffer << " to file, size " << size << llendl; - } - else - { - llwarns << "Found " << req.mURLBuffer << " to be zero size" << llendl; - xfer_result = LL_ERR_ASSET_REQUEST_FAILED; - } - } - else - { - xfer_result = curl_result == HTTP_MISSING ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED; - llinfos << "Failure downloading " << req.mURLBuffer << - " with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl; - } - } - - fclose(fp); - if (xfer_result) - { - LLFile::remove(filename); - } - return xfer_result; -} - - -// static -size_t LLHTTPAssetStorage::curlFileDownCallback(void *data, size_t size, size_t nmemb, void *user_data) -{ - CURL *curl_handle = (CURL *)user_data; - LLHTTPAssetRequest *req = NULL; - curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &req); - - if (! req->mFP) - { - llwarns << "Missing mFP, aborting curl file download callback!" << llendl; - return 0; - } - - return fwrite(data, size, nmemb, req->mFP); -} - -LLAssetStorage::request_list_t* LLHTTPAssetStorage::getRunningList(LLAssetStorage::ERequestType rt) -{ - switch (rt) - { - case RT_DOWNLOAD: - return &mRunningDownloads; - case RT_UPLOAD: - return &mRunningUploads; - case RT_LOCALUPLOAD: - return &mRunningLocalUploads; - default: - return NULL; - } -} - -const LLAssetStorage::request_list_t* LLHTTPAssetStorage::getRunningList(LLAssetStorage::ERequestType rt) const -{ - switch (rt) - { - case RT_DOWNLOAD: - return &mRunningDownloads; - case RT_UPLOAD: - return &mRunningUploads; - case RT_LOCALUPLOAD: - return &mRunningLocalUploads; - default: - return NULL; - } -} - - -void LLHTTPAssetStorage::addRunningRequest(ERequestType rt, LLHTTPAssetRequest* request) -{ - request_list_t* requests = getRunningList(rt); - if (requests) - { - requests->push_back(request); - } - else - { - llerrs << "LLHTTPAssetStorage::addRunningRequest - Request is not an upload OR download, this is bad!" << llendl; - } -} - -void LLHTTPAssetStorage::removeRunningRequest(ERequestType rt, LLHTTPAssetRequest* request) -{ - request_list_t* requests = getRunningList(rt); - if (requests) - { - requests->remove(request); - } - else - { - llerrs << "LLHTTPAssetStorage::removeRunningRequest - Destroyed request is not an upload OR download, this is bad!" << llendl; - } -} - -// virtual -void LLHTTPAssetStorage::addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name) -{ - if (agent_id.isNull() || asset_id.isNull()) - { - llwarns << "TAT: addTempAssetData bad id's asset_id: " << asset_id << " agent_id: " << agent_id << llendl; - return; - } - - LLTempAssetData temp_asset_data; - temp_asset_data.mAssetID = asset_id; - temp_asset_data.mAgentID = agent_id; - temp_asset_data.mHostName = host_name; - - mTempAssets[asset_id] = temp_asset_data; -} - -// virtual -BOOL LLHTTPAssetStorage::hasTempAssetData(const LLUUID& texture_id) const -{ - uuid_tempdata_map::const_iterator citer = mTempAssets.find(texture_id); - BOOL found = (citer != mTempAssets.end()); - return found; -} - -// virtual -std::string LLHTTPAssetStorage::getTempAssetHostName(const LLUUID& texture_id) const -{ - uuid_tempdata_map::const_iterator citer = mTempAssets.find(texture_id); - if (citer != mTempAssets.end()) - { - return citer->second.mHostName; - } - else - { - return std::string(); - } -} - -// virtual -LLUUID LLHTTPAssetStorage::getTempAssetAgentID(const LLUUID& texture_id) const -{ - uuid_tempdata_map::const_iterator citer = mTempAssets.find(texture_id); - if (citer != mTempAssets.end()) - { - return citer->second.mAgentID; - } - else - { - return LLUUID::null; - } -} - -// virtual -void LLHTTPAssetStorage::removeTempAssetData(const LLUUID& asset_id) -{ - mTempAssets.erase(asset_id); -} - -// virtual -void LLHTTPAssetStorage::removeTempAssetDataByAgentID(const LLUUID& agent_id) -{ - uuid_tempdata_map::iterator it = mTempAssets.begin(); - uuid_tempdata_map::iterator end = mTempAssets.end(); - - while (it != end) - { - const LLTempAssetData& asset_data = it->second; - if (asset_data.mAgentID == agent_id) - { - mTempAssets.erase(it++); - } - else - { - ++it; - } - } -} - -std::string LLHTTPAssetStorage::getBaseURL(const LLUUID& asset_id, LLAssetType::EType asset_type) -{ - if (LLAssetType::AT_TEXTURE == asset_type) - { - uuid_tempdata_map::const_iterator citer = mTempAssets.find(asset_id); - if (citer != mTempAssets.end()) - { - const std::string& host_name = citer->second.mHostName; - std::string url = llformat(LOCAL_ASSET_URL_FORMAT, host_name.c_str()); - return url; - } - } - - return mBaseURL; -} - -void LLHTTPAssetStorage::dumpTempAssetData(const LLUUID& avatar_id) const -{ - uuid_tempdata_map::const_iterator it = mTempAssets.begin(); - uuid_tempdata_map::const_iterator end = mTempAssets.end(); - S32 count = 0; - for ( ; it != end; ++it) - { - const LLTempAssetData& temp_asset_data = it->second; - if (avatar_id.isNull() - || avatar_id == temp_asset_data.mAgentID) - { - llinfos << "TAT: dump agent " << temp_asset_data.mAgentID - << " texture " << temp_asset_data.mAssetID - << " host " << temp_asset_data.mHostName - << llendl; - count++; - } - } - - if (avatar_id.isNull()) - { - llinfos << "TAT: dumped " << count << " entries for all avatars" << llendl; - } - else - { - llinfos << "TAT: dumped " << count << " entries for avatar " << avatar_id << llendl; - } -} - -void LLHTTPAssetStorage::clearTempAssetData() -{ - llinfos << "TAT: Clearing temp asset data map" << llendl; - mTempAssets.clear(); -} diff --git a/indra/llmessage/llhttpassetstorage.h b/indra/llmessage/llhttpassetstorage.h deleted file mode 100644 index f743ccf0a..000000000 --- a/indra/llmessage/llhttpassetstorage.h +++ /dev/null @@ -1,159 +0,0 @@ -/** - * @file llhttpassetstorage.h - * @brief Class for loading asset data to/from an external source over http. - * - * $LicenseInfo:firstyear=2003&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LLHTTPASSETSTORAGE_H -#define LLHTTPASSETSTORAGE_H - -#include "llassetstorage.h" -#include "curl/curl.h" - -class LLVFile; -class LLHTTPAssetRequest; -typedef void (*progress_callback)(void* userdata); - -struct LLTempAssetData; - -typedef std::map uuid_tempdata_map; - -class LLHTTPAssetStorage : public LLAssetStorage -{ -public: - LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, - LLVFS *vfs, LLVFS *static_vfs, - const LLHost &upstream_host, - const std::string& web_host, - const std::string& local_web_host, - const std::string& host_name); - - LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, - LLVFS *vfs, LLVFS *static_vfs, - const std::string& web_host, - const std::string& local_web_host, - const std::string& host_name); - - - virtual ~LLHTTPAssetStorage(); - - using LLAssetStorage::storeAssetData; // Unhiding virtuals... - - virtual void storeAssetData( - const LLUUID& uuid, - LLAssetType::EType atype, - LLStoreAssetCallback callback, - void* user_data, - bool temp_file = false, - bool is_priority = false, - bool store_local = false, - const LLUUID& requesting_agent_id = LLUUID::null, - bool user_waiting=FALSE, - F64 timeout=LL_ASSET_STORAGE_TIMEOUT); - - virtual void storeAssetData( - const std::string& filename, - const LLUUID& asset_id, - LLAssetType::EType atype, - LLStoreAssetCallback callback, - void* user_data, - bool temp_file, - bool is_priority, - bool user_waiting=FALSE, - F64 timeout=LL_ASSET_STORAGE_TIMEOUT); - - virtual LLSD getPendingDetails(ERequestType rt, - LLAssetType::EType asset_type, - const std::string& detail_prefix) const; - - virtual LLSD getPendingRequest(ERequestType rt, - LLAssetType::EType asset_type, - const LLUUID& asset_id) const; - - virtual bool deletePendingRequest(ERequestType rt, - LLAssetType::EType asset_type, - const LLUUID& asset_id); - - // Hack. One off curl download an URL to a file. Probably should be elsewhere. - // Only used by lldynamicstate. The API is broken, and should be replaced with - // a generic HTTP file fetch - Doug 9/25/06 - S32 getURLToFile(const LLUUID& uuid, LLAssetType::EType asset_type, const std::string &url, const std::string& filename, progress_callback callback, void *userdata); - - LLAssetRequest* findNextRequest(request_list_t& pending, request_list_t& running); - - void checkForTimeouts(); - - static size_t curlDownCallback(void *data, size_t size, size_t nmemb, void *user_data); - static size_t curlFileDownCallback(void *data, size_t size, size_t nmemb, void *user_data); - static size_t curlUpCallback(void *data, size_t size, size_t nmemb, void *user_data); - static size_t nullOutputCallback(void *data, size_t size, size_t nmemb, void *user_data); - - // Should only be used by the LLHTTPAssetRequest - void addRunningRequest(ERequestType rt, LLHTTPAssetRequest* request); - void removeRunningRequest(ERequestType rt, LLHTTPAssetRequest* request); - - request_list_t* getRunningList(ERequestType rt); - const request_list_t* getRunningList(ERequestType rt) const; - - // Temp assets are stored on sim nodes, they have agent ID and location data associated with them. - virtual void addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name); - virtual BOOL hasTempAssetData(const LLUUID& texture_id) const; - virtual std::string getTempAssetHostName(const LLUUID& texture_id) const; - virtual LLUUID getTempAssetAgentID(const LLUUID& texture_id) const; - virtual void removeTempAssetData(const LLUUID& asset_id); - virtual void removeTempAssetDataByAgentID(const LLUUID& agent_id); - - // Pass LLUUID::null for all - virtual void dumpTempAssetData(const LLUUID& avatar_id) const; - virtual void clearTempAssetData(); - -protected: - void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, - void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat), - void *user_data, BOOL duplicate, BOOL is_priority); - -private: - void _init(const std::string& web_host, const std::string& local_web_host, const std::string& host_name); - - // This will return the correct base URI for any http asset request - std::string getBaseURL(const LLUUID& asset_id, LLAssetType::EType asset_type); - - // Check for running uploads that have timed out - // Bump these to the back of the line to let other uploads complete. - void bumpTimedOutUploads(); - -protected: - std::string mBaseURL; - std::string mLocalBaseURL; - std::string mHostName; - - CURLM *mCurlMultiHandle; - - request_list_t mRunningDownloads; - request_list_t mRunningUploads; - request_list_t mRunningLocalUploads; - - uuid_tempdata_map mTempAssets; -}; - -#endif diff --git a/indra/llmessage/lliopipe.h b/indra/llmessage/lliopipe.h index cbd17b5a3..2def3229f 100644 --- a/indra/llmessage/lliopipe.h +++ b/indra/llmessage/lliopipe.h @@ -55,11 +55,11 @@ void pump_debug(const char *file, S32 line); /** * intrusive pointer support */ -namespace boost -{ +//namespace boost +//{ void intrusive_ptr_add_ref(LLIOPipe* p); void intrusive_ptr_release(LLIOPipe* p); -}; +//}; /** * @class LLIOPipe @@ -250,13 +250,13 @@ protected: LLPumpIO* pump) = 0; private: - friend void boost::intrusive_ptr_add_ref(LLIOPipe* p); - friend void boost::intrusive_ptr_release(LLIOPipe* p); + friend void /*boost::*/intrusive_ptr_add_ref(LLIOPipe* p); + friend void /*boost::*/intrusive_ptr_release(LLIOPipe* p); U32 mReferenceCount; }; -namespace boost -{ +//namespace boost +//{ inline void intrusive_ptr_add_ref(LLIOPipe* p) { ++p->mReferenceCount; @@ -268,7 +268,7 @@ namespace boost delete p; } } -}; +//}; #if 0 diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp index 932cbf375..01d78ed3e 100644 --- a/indra/llmessage/llregionpresenceverifier.cpp +++ b/indra/llmessage/llregionpresenceverifier.cpp @@ -32,8 +32,8 @@ #include "net.h" #include "message.h" -namespace boost -{ +//namespace boost +//{ void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p) { ++p->mReferenceCount; @@ -46,7 +46,7 @@ namespace boost delete p; } } -}; +//}; LLRegionPresenceVerifier::Response::~Response() { diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h index 5e8251e51..9b45e78b5 100644 --- a/indra/llmessage/llregionpresenceverifier.h +++ b/indra/llmessage/llregionpresenceverifier.h @@ -89,10 +89,10 @@ public: }; }; -namespace boost -{ +//namespace boost +//{ void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p); void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p); -}; +//}; #endif //LL_LLREGIONPRESENCEVERIFIER_H diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp index b9cddc8e4..090ab2a00 100644 --- a/indra/llmessage/llxfermanager.cpp +++ b/indra/llmessage/llxfermanager.cpp @@ -261,7 +261,7 @@ U32 LLXferManager::numActiveListEntries(LLXfer *list_head) while (list_head) { - if ((list_head->mStatus == e_LL_XFER_IN_PROGRESS)) + if (list_head->mStatus == e_LL_XFER_IN_PROGRESS) { num_entries++; } diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index 85aef5da0..6e232aa24 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -36,6 +36,7 @@ #include #include #else + #include #include #include #include diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp index d84fe0a49..de9725e8a 100644 --- a/indra/llmessage/tests/llcurl_stub.cpp +++ b/indra/llmessage/tests/llcurl_stub.cpp @@ -77,8 +77,8 @@ void LLCurl::Responder::result(LLSD const&) { } -namespace boost -{ +//namespace boost +//{ void intrusive_ptr_add_ref(LLCurl::Responder* p) { ++p->mReferenceCount; @@ -91,5 +91,5 @@ namespace boost delete p; } } -}; +//}; diff --git a/indra/llplugin/llpluginclassbasic.cpp b/indra/llplugin/llpluginclassbasic.cpp index 0567b157f..e3c587642 100644 --- a/indra/llplugin/llpluginclassbasic.cpp +++ b/indra/llplugin/llpluginclassbasic.cpp @@ -52,15 +52,16 @@ LLPluginClassBasic::~LLPluginClassBasic() delete mPlugin; } -bool LLPluginClassBasic::init(std::string const& launcher_filename, std::string const& plugin_filename, bool debug) +bool LLPluginClassBasic::init(std::string const& launcher_filename, std::string const& plugin_dir, std::string const& plugin_filename, bool debug) { LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL; + LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL; LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL; mPlugin = new LLPluginProcessParent(this); mPlugin->setSleepTime(mSleepTime); - mPlugin->init(launcher_filename, plugin_filename, debug); + mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug); return init_impl(); } diff --git a/indra/llplugin/llpluginclassbasic.h b/indra/llplugin/llpluginclassbasic.h index 6c0602608..b7f9a3a86 100644 --- a/indra/llplugin/llpluginclassbasic.h +++ b/indra/llplugin/llpluginclassbasic.h @@ -53,7 +53,10 @@ public: virtual ~LLPluginClassBasic(); // Local initialization, called when creating a plugin process. Return true if successful. - bool init(std::string const& launcher_filename, std::string const& plugin_filename, bool debug); + bool init(std::string const& launcher_filename, + std::string const& plugin_dir, + std::string const& plugin_filename, + bool debug); // Undoes everything init did. Called when destroying a plugin process. void reset(void); diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index de208cb44..c71515496 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -484,6 +484,7 @@ void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity ) message.setValue( "maturity", maturity ); sendMessage( message ); } + void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers) { if(type == MOUSE_EVENT_MOVE) @@ -573,7 +574,15 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie } break; } - + +#if LL_DARWIN + if(modifiers & MASK_ALT) + { + // Option-key modified characters should be handled by the unicode input path instead of this one. + result = false; + } +#endif + if(result) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event"); @@ -731,6 +740,14 @@ void LLPluginClassMedia::setJavascriptEnabled(const bool enabled) sendMessage(message); } + +void LLPluginClassMedia::enableMediaPluginDebugging( bool enable ) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "enable_media_plugin_debugging"); + message.setValueBoolean( "enable", enable ); + sendMessage( message ); +} + void LLPluginClassMedia::setTarget(const std::string &target) { mTarget = target; @@ -795,7 +812,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mDirtyRect.unionWith(newDirtyRect); } - LL_DEBUGS("PluginUpdated") << "adjusted incoming rect is: (" + LL_DEBUGS("PluginUpdated") << "adjusted incoming rect is: (" << newDirtyRect.mLeft << ", " << newDirtyRect.mTop << ", " << newDirtyRect.mRight << ", " @@ -958,6 +975,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mAuthURL = message.getValue("url"); mAuthRealm = message.getValue("realm"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST); + } + else if(message_name == "debug_message") + { + mDebugMessageText = message.getValue("message_text"); + mDebugMessageLevel = message.getValue("message_level"); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_DEBUG_MESSAGE); } else { @@ -1103,6 +1126,14 @@ void LLPluginClassMedia::focus(bool focused) sendMessage(message); } +void LLPluginClassMedia::set_page_zoom_factor( double factor ) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_page_zoom_factor"); + + message.setValueReal("factor", factor); + sendMessage(message); +} + void LLPluginClassMedia::clear_cache() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache"); @@ -1186,6 +1217,13 @@ void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent) sendMessage(message); } +void LLPluginClassMedia::showWebInspector( bool show ) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "show_web_inspector"); + message.setValueBoolean("show", true); // only open for now - closed manually by user + sendMessage(message); +} + void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened"); diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 8136e9cb7..b58d0c95f 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -112,6 +112,9 @@ public: void scrollEvent(int x, int y, MASK modifiers); + // enable/disable media plugin debugging messages and info spam + void enableMediaPluginDebugging( bool enable ); + // Javascript <-> viewer events void jsEnableObject( bool enable ); void jsAgentLocationEvent( double x, double y, double z ); @@ -167,6 +170,7 @@ public: bool pluginSupportsMediaBrowser(void); void focus(bool focused); + void set_page_zoom_factor( double factor ); void clear_cache(); void clear_cookies(); void set_cookies(const std::string &cookies); @@ -178,6 +182,7 @@ public: void browse_back(); void set_status_redirect(int code, const std::string &url); void setBrowserUserAgent(const std::string& user_agent); + void showWebInspector( bool show ); void proxyWindowOpened(const std::string &target, const std::string &uuid); void proxyWindowClosed(const std::string &uuid); void ignore_ssl_cert_errors(bool ignore); @@ -213,6 +218,10 @@ public: // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE std::string getClickUUID() const { return mClickUUID; }; + // These are valid during MEDIA_EVENT_DEBUG_MESSAGE + std::string getDebugMessageText() const { return mDebugMessageText; }; + std::string getDebugMessageLevel() const { return mDebugMessageLevel; }; + // This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE S32 getStatusCode() const { return mStatusCode; }; @@ -271,7 +280,7 @@ protected: protected: LLPluginClassMediaOwner *mOwner; - + bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true S32 mRequestedTextureDepth; LLGLenum mRequestedTextureInternalFormat; @@ -358,6 +367,8 @@ protected: std::string mClickNavType; std::string mClickTarget; std::string mClickUUID; + std::string mDebugMessageText; + std::string mDebugMessageLevel; S32 mGeometryX; S32 mGeometryY; S32 mGeometryWidth; diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h index 0083e0c41..4a739cf86 100644 --- a/indra/llplugin/llpluginclassmediaowner.h +++ b/indra/llplugin/llpluginclassmediaowner.h @@ -71,6 +71,8 @@ public: MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog + MEDIA_EVENT_DEBUG_MESSAGE, // plugin sending back debug information for host to process + MEDIA_EVENT_LINK_HOVERED // Got a "link hovered" event from the plugin } EMediaEvent; diff --git a/indra/llplugin/llplugininstance.cpp b/indra/llplugin/llplugininstance.cpp index 15e1d347a..a53f67087 100644 --- a/indra/llplugin/llplugininstance.cpp +++ b/indra/llplugin/llplugininstance.cpp @@ -40,8 +40,13 @@ #include "linden_common.h" #include "llplugininstance.h" + #include "llaprpool.h" +#if LL_WINDOWS +#include "direct.h" // needed for _chdir() +#endif + /** Virtual destructor. */ LLPluginInstanceMessageListener::~LLPluginInstanceMessageListener() { @@ -83,10 +88,24 @@ LLPluginInstance::~LLPluginInstance() * @param[in] plugin_file Name of plugin dll/dylib/so. TODO:DOC is this correct? see .h * @return 0 if successful, APR error code or error code from the plugin's init function on failure. */ -int LLPluginInstance::load(std::string &plugin_file) +int LLPluginInstance::load(const std::string& plugin_dir, std::string &plugin_file) { pluginInitFunction init_function = NULL; + if ( plugin_dir.length() ) + { +#if LL_WINDOWS + // VWR-21275: + // *SOME* Windows systems fail to load the Qt plugins if the current working + // directory is not the same as the directory with the Qt DLLs in. + // This should not cause any run time issues since we are changing the cwd for the + // plugin shell process and not the viewer. + // Changing back to the previous directory is not necessary since the plugin shell + // quits once the plugin exits. + _chdir( plugin_dir.c_str() ); +#endif + }; + #if LL_LINUX && defined(LL_STANDALONE) void *dso_handle = dlopen(plugin_file.c_str(), RTLD_NOW | RTLD_GLOBAL); int result = (!dso_handle)?APR_EDSOOPEN:apr_os_dso_handle_put(&mDSOHandle, @@ -99,7 +118,22 @@ int LLPluginInstance::load(std::string &plugin_file) if(result != APR_SUCCESS) { char buf[1024]; - apr_dso_error(mDSOHandle, buf, sizeof(buf)); +#if LL_LINUX && defined(LL_STANDALONE) + if (!dso_handle) + { + char* error = dlerror(); + buf[0] = 0; + if (error) + { + strncpy(buf, dlerror(), sizeof(buf)); + } + buf[sizeof(buf) - 1] = 0; + } + else +#endif + { + apr_dso_error(mDSOHandle, buf, sizeof(buf)); + } #if LL_LINUX && defined(LL_STANDALONE) LL_WARNS("Plugin") << "plugin load " << plugin_file << " failed with error " << result << " , additional info string: " << buf << LL_ENDL; diff --git a/indra/llplugin/llplugininstance.h b/indra/llplugin/llplugininstance.h index b2b107bab..c77da97ba 100644 --- a/indra/llplugin/llplugininstance.h +++ b/indra/llplugin/llplugininstance.h @@ -64,7 +64,7 @@ public: // Load a plugin dll/dylib/so // Returns 0 if successful, APR error code or error code returned from the plugin's init function on failure. - int load(std::string &plugin_file); + int load(const std::string& plugin_dir, std::string &plugin_file); // Sends a message to the plugin. void sendMessage(const std::string &message); diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp index d014cf9bb..a85a0343d 100644 --- a/indra/llplugin/llpluginprocesschild.cpp +++ b/indra/llplugin/llpluginprocesschild.cpp @@ -146,7 +146,7 @@ void LLPluginProcessChild::idle(void) if(!mPluginFile.empty()) { mInstance = new LLPluginInstance(this); - if(mInstance->load(mPluginFile) == 0) + if(mInstance->load(mPluginDir, mPluginFile) == 0) { mHeartbeat.start(); mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS); @@ -372,6 +372,7 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) if(message_name == "load_plugin") { mPluginFile = parsed.getValue("file"); + mPluginDir = parsed.getValue("dir"); } else if(message_name == "shm_add") { diff --git a/indra/llplugin/llpluginprocesschild.h b/indra/llplugin/llpluginprocesschild.h index 66082db7c..53dcccb81 100644 --- a/indra/llplugin/llpluginprocesschild.h +++ b/indra/llplugin/llpluginprocesschild.h @@ -101,6 +101,7 @@ private: LLSocket::ptr_t mSocket; std::string mPluginFile; + std::string mPluginDir; LLPluginInstance *mInstance; diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 685485fc1..cdb8ec88a 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -114,7 +114,6 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner) // Don't start the timer here -- start it when we actually launch the plugin process. mHeartbeat.stop(); - // Don't add to the global list until fully constructed. { @@ -173,10 +172,12 @@ void LLPluginProcessParent::errorState(void) setState(STATE_ERROR); } -void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug) +void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug) { mProcess.setExecutable(launcher_filename); + mProcess.setWorkingDirectory(plugin_dir); mPluginFile = plugin_filename; + mPluginDir = plugin_dir; mCPUUsage = 0.0f; mDebug = debug; setState(STATE_INITIALIZED); @@ -483,6 +484,7 @@ void LLPluginProcessParent::idle(void) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin"); message.setValue("file", mPluginFile); + message.setValue("dir", mPluginDir); sendMessage(message); } diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h index 28e8edd19..d5a08c435 100644 --- a/indra/llplugin/llpluginprocessparent.h +++ b/indra/llplugin/llpluginprocessparent.h @@ -67,6 +67,7 @@ public: ~LLPluginProcessParent(); void init(const std::string &launcher_filename, + const std::string &plugin_dir, const std::string &plugin_filename, bool debug); @@ -166,12 +167,13 @@ private: LLProcessLauncher mProcess; std::string mPluginFile; + std::string mPluginDir; LLPluginProcessParentOwner *mOwner; - + typedef std::map sharedMemoryRegionsType; sharedMemoryRegionsType mSharedMemoryRegions; - + LLSD mMessageClassVersions; std::string mPluginVersionString; @@ -194,7 +196,7 @@ private: apr_pollfd_t mPollFD; LLAPRPool mPollFDPool; static apr_pollset_t *sPollSet; - static LLAPRPool sPollSetPool; + static LLAPRPool sPollSetPool; static bool sPollsetNeedsRebuild; static LLMutex *sInstancesMutex; static std::list sInstances; diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp index 90ca3fea7..b841a30e1 100644 --- a/indra/llplugin/slplugin/slplugin.cpp +++ b/indra/llplugin/slplugin/slplugin.cpp @@ -124,9 +124,14 @@ BOOL PreventSetUnhandledExceptionFilter() newJump[ 0 ] = 0xE9; // JMP absolute memcpy( &newJump[ 1 ], &dwRelativeAddr, sizeof( pNewFunc ) ); - SIZE_T bytesWritten; - BOOL bRet = WriteProcessMemory( GetCurrentProcess(), pOrgEntry, newJump, sizeof( pNewFunc ) + 1, &bytesWritten ); - return bRet; + //SIZE_T bytesWritten; + //BOOL bRet = WriteProcessMemory( GetCurrentProcess(), pOrgEntry, newJump, sizeof( pNewFunc ) + 1, &bytesWritten ); + DWORD oldProtect; + BOOL bRet = VirtualProtect(pOrgEntry, sizeof(pNewFunc) + 1, PAGE_READWRITE, &oldProtect); + if (!bRet) return FALSE; + memcpy(pOrgEntry, newJump, sizeof(pNewFunc) + 1); + VirtualProtect(pOrgEntry, sizeof(pNewFunc) + 1, oldProtect, &oldProtect); + return TRUE; #else return FALSE; #endif @@ -186,7 +191,7 @@ int main(int argc, char **argv) #ifdef CWDEBUG Debug( libcw_do.margin().assign("SLPlugin ", 9) ); Debug(debug::init()); - // Uncomment this to automatically open a terminal with gdb. Requires SNOW-173. + // Uncomment this to automatically open a terminal with gdb. //Debug(attach_gdb()); #endif diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 298308ae8..83ea3e3eb 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -223,7 +223,7 @@ void LLPrimitive::setPCode(const U8 p_code) } //=============================================================== -const LLTextureEntry* LLPrimitive::getTE(const U8 index) const +LLTextureEntry* LLPrimitive::getTE(const U8 index) const { return mTextureList.getTexture(index); } @@ -1076,9 +1076,8 @@ S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 dat // Pack information about all texture entries into container: // { TextureEntry Variable 2 } // Includes information about image ID, color, scale S,T, offset S,T and rotation -BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys, int shield, std::string client_str) const +BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const { - LLUUID client_tag = LLUUID(client_str); const U32 MAX_TES = 32; U8 image_ids[MAX_TES*16]; @@ -1097,8 +1096,6 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys, int shield, std::strin U8 *cur_ptr = packed_buffer; S32 last_face_index = llmin((U32) getNumTEs(), MAX_TES) - 1; - - if (client_str == "c228d1cf-4b5d-4ba8-84f4-899a0796aa97") shield = 0; if (last_face_index > -1) { @@ -1108,18 +1105,7 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys, int shield, std::strin for (face_index = 0; face_index <= last_face_index; face_index++) { // Directly sending image_ids is not safe! - if(shield && !(face_index == 20 || face_index == 8 || face_index == 9 || face_index == 10 || face_index == 11 || face_index == 18 || face_index == 19)) - { - S8 f_f_i = face_index; - if(face_index == 0)f_f_i = 64; - if(face_index == 5)f_f_i = 9; - if(face_index == 6)f_f_i = 10; - if(face_index == 3)f_f_i = 11; - if(f_f_i == face_index)memcpy(&image_ids[face_index*16],LLUUID("c228d1cf-4b5d-4ba8-84f4-899a0796aa97").mData,16); - else if(f_f_i == 64)memcpy(&image_ids[face_index*16],client_tag.mData,16); - else memcpy(&image_ids[face_index*16],LLUUID("4934f1bf-3b1f-cf4f-dbdf-a72550d05bc6").mData,16);//grey block - } - else memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */ + memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */ // Cast LLColor4 to LLColor4U coloru.setVec( getTE(face_index)->getColor() ); diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 126d96f91..5808ffc3c 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -334,7 +334,7 @@ public: // Modify texture entry properties inline BOOL validTE(const U8 te_num) const; - const LLTextureEntry *getTE(const U8 te_num) const; + LLTextureEntry* getTE(const U8 te_num) const; virtual void setNumTEs(const U8 num_tes); virtual void setAllTETextures(const LLUUID &tex_id); @@ -364,7 +364,7 @@ public: void copyTEs(const LLPrimitive *primitive); S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const; S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type); - BOOL packTEMessage(LLMessageSystem *mesgsys, int shield = 0, std::string client_str = "") const; + BOOL packTEMessage(LLMessageSystem *mesgsys) const; BOOL packTEMessage(LLDataPacker &dp) const; S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name); S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 45a3b1817..362452d83 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -81,7 +81,7 @@ void LLCubeMap::initGL() { U32 texname = 0; - LLImageGL::generateTextures(1, &texname); + LLImageGL::generateTextures(LLTexUnit::TT_CUBE_MAP, GL_RGB8, 1, &texname); for (int i = 0; i < 6; i++) { diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 286c5b3a5..5b327b4ed 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -57,8 +57,9 @@ std::string LLFontGL::sAppDir; LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f); LLFontRegistry* LLFontGL::sFontRegistry = NULL; -LLCoordFont LLFontGL::sCurOrigin; -std::vector LLFontGL::sOriginStack; +LLCoordGL LLFontGL::sCurOrigin; +F32 LLFontGL::sCurDepth; +std::vector > LLFontGL::sOriginStack; const F32 EXT_X_BEARING = 1.f; const F32 EXT_Y_BEARING = 0.f; @@ -221,7 +222,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons gGL.pushMatrix(); gGL.loadIdentity(); - gGL.translatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ); + gGL.translatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurDepth); // this code snaps the text origin to a pixel grid to start with F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX); diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index fc59ce0fd..11ed81c37 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -212,8 +212,9 @@ public: static std::string getFontPathLocal(); static std::string getFontPathSystem(); - static LLCoordFont sCurOrigin; - static std::vector sOriginStack; + static LLCoordGL sCurOrigin; + static F32 sCurDepth; + static std::vector > sOriginStack; static LLColor4 sShadowColor; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 485ab205f..92d095b80 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -2,31 +2,25 @@ * @file llgl.cpp * @brief LLGL implementation * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -263,6 +257,12 @@ PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample = NULL; PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv = NULL; PFNGLSAMPLEMASKIPROC glSampleMaski = NULL; +//transform feedback (4.0 core) +PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = NULL; +PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL; +PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL; + //GL_ARB_debug_output PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL; PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB = NULL; @@ -436,6 +436,7 @@ LLGLManager::LLGLManager() : mHasDrawBuffers(FALSE), mHasTextureRectangle(FALSE), mHasTextureMultisample(FALSE), + mHasTransformFeedback(FALSE), mMaxSampleMaskWords(0), mMaxColorTextureSamples(0), mMaxDepthTextureSamples(0), @@ -573,7 +574,8 @@ bool LLGLManager::initGL() parse_gl_version( &mDriverVersionMajor, &mDriverVersionMinor, &mDriverVersionRelease, - &mDriverVersionVendorString ); + &mDriverVersionVendorString, + &mGLVersionString); mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f; @@ -591,7 +593,7 @@ bool LLGLManager::initGL() #endif } - if (mGLVersion >= 3.f && LLImageGL::sCompressTextures) + if (mGLVersion >= 2.1f && LLImageGL::sCompressTextures) { //use texture compression glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); } @@ -755,6 +757,11 @@ bool LLGLManager::initGL() } #endif + if (mIsIntel && mGLVersion <= 3.f) + { //never try to use framebuffer objects on older intel drivers (crashy) + mHasFramebufferObject = FALSE; + } + if (mHasFramebufferObject) { glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples); @@ -923,7 +930,6 @@ void LLGLManager::initExtensions() mHasMultitexture = glh_init_extensions("GL_ARB_multitexture"); mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts); mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts); - mHasMipMapGeneration = glh_init_extensions("GL_SGIS_generate_mipmap"); mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color"); mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic"); glh_init_extensions("GL_ARB_texture_cube_map"); @@ -948,11 +954,15 @@ void LLGLManager::initExtensions() ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); #endif mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts); + + mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f; + mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts); mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts); mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts); mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts); + mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE; #if !LL_DARWIN mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); #endif @@ -1194,7 +1204,14 @@ void LLGLManager::initExtensions() glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample"); glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv"); glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski"); - } + } + if (mHasTransformFeedback) + { + glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glBeginTransformFeedback"); + glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback"); + glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings"); + glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange"); + } if (mHasDebugOutput) { glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControlARB"); @@ -1891,7 +1908,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) glClientActiveTextureARB(GL_TEXTURE0_ARB); gGL.getTexUnit(0)->activate(); - if (gGLManager.mHasVertexShader) + if (gGLManager.mHasVertexShader && LLGLSLShader::sNoFixedFunction) { //make sure vertex attribs are all disabled GLint count; glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &count); @@ -1943,6 +1960,7 @@ LLGLState::LLGLState(LLGLenum state, S32 enabled) : case GL_COLOR_MATERIAL: case GL_FOG: case GL_LINE_STIPPLE: + case GL_POLYGON_STIPPLE: mState = 0; break; } @@ -2031,7 +2049,7 @@ void LLGLManager::initGLStates() //////////////////////////////////////////////////////////////////////////////// -void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific ) +void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string ) { // GL_VERSION returns a null-terminated string with the format: // .[.] [] @@ -2047,6 +2065,8 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor return; } + version_string->assign(version); + std::string ver_copy( version ); S32 len = (S32)strlen( version ); /* Flawfinder: ignore */ S32 i = 0; @@ -2408,3 +2428,63 @@ LLGLSquashToFarClip::~LLGLSquashToFarClip() gGL.matrixMode(LLRender::MM_MODELVIEW); } + + +LLGLSyncFence::LLGLSyncFence() +{ +#ifdef GL_ARB_sync + mSync = 0; +#endif +} + +LLGLSyncFence::~LLGLSyncFence() +{ +#ifdef GL_ARB_sync + if (mSync) + { + glDeleteSync(mSync); + } +#endif +} + +void LLGLSyncFence::placeFence() +{ +#ifdef GL_ARB_sync + if (mSync) + { + glDeleteSync(mSync); + } + mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); +#endif +} + +bool LLGLSyncFence::isCompleted() +{ + bool ret = true; +#ifdef GL_ARB_sync + if (mSync) + { + GLenum status = glClientWaitSync(mSync, 0, 1); + if (status == GL_TIMEOUT_EXPIRED) + { + ret = false; + } + } +#endif + return ret; +} + +void LLGLSyncFence::wait() +{ +#ifdef GL_ARB_sync + if (mSync) + { + while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED) + { //track the number of times we've waited here + static S32 waits = 0; + waits++; + } + } +#endif +} + diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 6817ec0f0..06f6155c9 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -2,31 +2,25 @@ * @file llgl.h * @brief LLGL definition * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -111,6 +105,7 @@ public: BOOL mHasDepthClamp; BOOL mHasTextureRectangle; BOOL mHasTextureMultisample; + BOOL mHasTransformFeedback; S32 mMaxSampleMaskWords; S32 mMaxColorTextureSamples; S32 mMaxDepthTextureSamples; @@ -148,6 +143,7 @@ public: S32 mGLSLVersionMajor; S32 mGLSLVersionMinor; std::string mDriverVersionVendorString; + std::string mGLVersionString; S32 mVRAM; // VRAM in MB S32 mGLMaxVertexRange; @@ -425,13 +421,39 @@ public: virtual void updateGL() = 0; }; +const U32 FENCE_WAIT_TIME_NANOSECONDS = 1000; //1 ms + +class LLGLFence +{ +public: + virtual void placeFence() = 0; + virtual bool isCompleted() = 0; + virtual void wait() = 0; + virtual ~LLGLFence() {} +}; + +class LLGLSyncFence : public LLGLFence +{ +public: +#ifdef GL_ARB_sync + GLsync mSync; +#endif + + LLGLSyncFence(); + virtual ~LLGLSyncFence(); + + void placeFence(); + bool isCompleted(); + void wait(); +}; + extern LLMatrix4 gGLObliqueProjectionInverse; #include "llglstates.h" void init_glstates(); -void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific ); +void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string ); extern BOOL gClothRipple; extern BOOL gNoRender; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index 7ccc0d819..9e3d9b96f 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -534,6 +534,13 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; extern PFNGLSAMPLEMASKIPROC glSampleMaski; +//transform feedback (4.0 core) +extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback; +extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback; +extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings; +extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; + + #elif LL_WINDOWS //---------------------------------------------------------------------------- // LL_WINDOWS @@ -765,6 +772,12 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; extern PFNGLSAMPLEMASKIPROC glSampleMaski; +//transform feedback (4.0 core) +extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback; +extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback; +extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings; +extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; + //GL_ARB_debug_output extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB; extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 1dfbde0b8..1c90d7658 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -134,7 +134,9 @@ void LLGLSLShader::unload() } BOOL LLGLSLShader::createShader(vector * attributes, - vector * uniforms) + vector * uniforms, + U32 varying_count, + const char** varyings) { //reloading, reset matrix hash values for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) @@ -142,6 +144,7 @@ BOOL LLGLSLShader::createShader(vector * attributes, mMatHash[i] = 0xFFFFFFFF; } mLightHash = 0xFFFFFFFF; + llassert_always(!mShaderFiles.empty()); BOOL success = TRUE; @@ -176,11 +179,18 @@ BOOL LLGLSLShader::createShader(vector * attributes, } static const LLCachedControl no_texture_indexing("ShyotlUseLegacyTextureBatching",false); - if (gGLManager.mGLVersion < 3.1f || no_texture_indexing) + if ((gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 3) || no_texture_indexing) { //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); } +#ifdef GL_INTERLEAVED_ATTRIBS + if (varying_count > 0 && varyings) + { + glTransformFeedbackVaryings(mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS); + } +#endif + // Map attributes and uniforms if (success) { @@ -228,13 +238,13 @@ BOOL LLGLSLShader::createShader(vector * attributes, } unbind(); } + return success; } BOOL LLGLSLShader::attachObject(std::string object) { - std::map &ShaderObjects = LLShaderMgr::instance()->mShaderObjects; - if (ShaderObjects.find(object) != ShaderObjects.end()) + if (LLShaderMgr::instance()->mShaderObjects.count(object) > 0) { stop_glerror(); glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mShaderObjects[object]); diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 6311d8410..2f64b0c9f 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -82,7 +82,9 @@ public: void unload(); BOOL createShader(std::vector * attributes, - std::vector * uniforms); + std::vector * uniforms, + U32 varying_count = 0, + const char** varyings = NULL); BOOL attachObject(std::string object); void attachObject(GLhandleARB object); void attachObjects(GLhandleARB* objects = NULL, S32 count = 0); diff --git a/indra/llrender/llgltypes.h b/indra/llrender/llgltypes.h index 9b0e81fae..6c217ef72 100644 --- a/indra/llrender/llgltypes.h +++ b/indra/llrender/llgltypes.h @@ -2,31 +2,25 @@ * @file llgltypes.h * @brief LLGL definition * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index b8e14aae0..1e698adfc 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -42,13 +42,17 @@ #include "llmath.h" #include "llgl.h" +#include "llglslshader.h" #include "llrender.h" -//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- const F32 MIN_TEXTURE_LIFETIME = 10.f; +//which power of 2 is i? +//assumes i is a power of 2 > 0 +U32 wpo2(U32 i); + //statics -LLGLuint LLImageGL::sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS] = { 0 }; U32 LLImageGL::sUniqueCount = 0; U32 LLImageGL::sBindCount = 0; @@ -56,7 +60,8 @@ S32 LLImageGL::sGlobalTextureMemoryInBytes = 0; S32 LLImageGL::sBoundTextureMemoryInBytes = 0; S32 LLImageGL::sCurBoundTextureMemory = 0; S32 LLImageGL::sCount = 0; -std::list LLImageGL::sDeadTextureList; +LLImageGL::dead_texturelist_t LLImageGL::sDeadTextureList[LLTexUnit::TT_NONE]; +U32 LLImageGL::sCurTexName = 1; BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; F32 LLImageGL::sLastFrameTime = 0.f; @@ -79,7 +84,7 @@ std::vector LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; S32 LLImageGL::sCurTexSizeBar = -1 ; S32 LLImageGL::sCurTexPickSize = -1 ; LLPointer LLImageGL::sHighlightTexturep = NULL; -S32 LLImageGL::sMaxCatagories = 1 ; +S32 LLImageGL::sMaxCategories = 1 ; std::vector LLImageGL::sTextureMemByCategory; std::vector LLImageGL::sTextureMemByCategoryBound ; @@ -181,11 +186,11 @@ BOOL is_little_endian() //static void LLImageGL::initClass(S32 num_catagories) { - sMaxCatagories = num_catagories ; + sMaxCategories = num_catagories ; - sTextureMemByCategory.resize(sMaxCatagories); - sTextureMemByCategoryBound.resize(sMaxCatagories) ; - sTextureCurMemByCategoryBound.resize(sMaxCatagories) ; + sTextureMemByCategory.resize(sMaxCategories); + sTextureMemByCategoryBound.resize(sMaxCategories) ; + sTextureCurMemByCategoryBound.resize(sMaxCategories) ; } //static @@ -347,7 +352,10 @@ void LLImageGL::destroyGL(BOOL save_state) glimage->mSaveData = NULL ; } else + { + glimage->mSaveDiscardLevel = glimage->mCurrentDiscardLevel; stored_count++; + } } glimage->destroyGLTexture(); @@ -374,13 +382,14 @@ void LLImageGL::restoreGL() } if (glimage->mSaveData.notNull()) { - if (glimage->getComponents() && glimage->mSaveData->getComponents()) + if (glimage->getComponents() && glimage->mSaveData->getComponents() && glimage->mSaveDiscardLevel >= 0) { - glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, TRUE, glimage->getCategory()); + glimage->createGLTexture(glimage->mSaveDiscardLevel, glimage->mSaveData, 0, TRUE, glimage->getCategory()); stop_glerror(); recovered_count++; } glimage->mSaveData = NULL; // deletes data + glimage->mSaveDiscardLevel = -1; } } llinfos << "Restored " << recovered_count << " images" << llendl; @@ -425,7 +434,7 @@ BOOL LLImageGL::create(LLPointer& dest, const LLImageRaw* imageraw, B //---------------------------------------------------------------------------- LLImageGL::LLImageGL(BOOL usemipmaps) - : mSaveData(0) + : mSaveData(0), mSaveDiscardLevel(-1) { init(usemipmaps); setSize(0, 0, 0); @@ -434,7 +443,7 @@ LLImageGL::LLImageGL(BOOL usemipmaps) } LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps) - : mSaveData(0) + : mSaveData(0), mSaveDiscardLevel(-1) { llassert( components <= 4 ); init(usemipmaps); @@ -444,7 +453,7 @@ LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps) } LLImageGL::LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps) - : mSaveData(0) + : mSaveData(0), mSaveDiscardLevel(-1) { init(usemipmaps); setSize(0, 0, 0); @@ -493,8 +502,9 @@ void LLImageGL::init(BOOL usemipmaps) mAllowCompression = true; mTarget = GL_TEXTURE_2D; - mBindTarget = LLTexUnit::TT_TEXTURE; - mHasMipMaps = false; + mBindTarget = LLTexUnit::TT_TEXTURE; + mHasMipMaps = false; + mMipLevels = -1; mIsResident = 0; @@ -679,19 +689,32 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { -// LLFastTimer t1(FTM_TEMP1); bool is_compressed = false; if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { is_compressed = true; } -// LLFastTimer t2(FTM_TEMP2); - llverify(gGL.getTexUnit(0)->bind(this)); + + + if (mUseMipMaps) + { + //set has mip maps to true before binding image so tex parameters get set properly + gGL.getTexUnit(0)->unbind(mBindTarget); + mHasMipMaps = true; + mTexOptionsDirty = true; + setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + } + else + { + mHasMipMaps = false; + } + + llverify(gGL.getTexUnit(0)->bind(this)); + if (mUseMipMaps) { -// LLFastTimer t2(FTM_TEMP3); if (data_hasmips) { // NOTE: data_in points to largest image; smaller images @@ -702,6 +725,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) S32 w = getWidth(d); S32 h = getHeight(d); S32 gl_level = d-mCurrentDiscardLevel; + + mMipLevels = llmax(mMipLevels, gl_level); + if (d > mCurrentDiscardLevel) { data_in -= dataFormatBytes(mFormatPrimary, w, h); // see above comment @@ -745,10 +771,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { if (mAutoGenMips) { - if (!gGLManager.mHasFramebufferObject) - { - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE); - } stop_glerror(); { // LLFastTimer t2(FTM_TEMP4); @@ -762,6 +784,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) S32 w = getWidth(mCurrentDiscardLevel); S32 h = getHeight(mCurrentDiscardLevel); + mMipLevels = wpo2(llmax(w, h)); + + //use legacy mipmap generation mode + glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE); + LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, mFormatPrimary, mFormatType, @@ -777,17 +804,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) stop_glerror(); } } - - if (gGLManager.mHasFramebufferObject) - { - //GL_EXT_framebuffer_object implies glGenerateMipmap - glGenerateMipmap(LLTexUnit::getInternalType(mBindTarget)); - } } else { // Create mips by hand - // about 30% faster than autogen on ATI 9800, 50% slower on nVidia 4800 // ~4x faster than gluBuild2DMipmaps S32 width = getWidth(mCurrentDiscardLevel); S32 height = getHeight(mCurrentDiscardLevel); @@ -797,6 +817,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) const U8* cur_mip_data = 0; S32 prev_mip_size = 0; S32 cur_mip_size = 0; + + mMipLevels = nummips; + for (int m=0; msecond.empty(); + } + + for (S32 i = 0; i < numTextures; ++i) + { + if (!empty) + { + textures[i] = iter->second.front(); + iter->second.pop_front(); + empty = iter->second.empty(); + } + else + { + textures[i] = sCurTexName++; + } + } } // static -void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate) +void LLImageGL::deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip_levels, S32 numTextures, U32 *textures, bool immediate) { - for (S32 i = 0; i < numTextures; i++) + if (gGLManager.mInited) { - sDeadTextureList.push_back(textures[i]); - } + if (format == 0 || type == LLTexUnit::TT_CUBE_MAP || mip_levels == -1) + { //unknown internal format or unknown number of mip levels, not safe to reuse + glDeleteTextures(numTextures, textures); + } + else + { + for (S32 i = 0; i < numTextures; ++i) + { //remove texture from VRAM by setting its size to zero + for (S32 j = 0; j <= mip_levels; j++) + { + gGL.getTexUnit(0)->bindManual(type, textures[i]); - if (immediate) + glTexImage2D(LLTexUnit::getInternalType(type), j, format, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + } + + llassert(std::find(sDeadTextureList[type][format].begin(), + sDeadTextureList[type][format].end(), textures[i]) == + sDeadTextureList[type][format].end()); + + sDeadTextureList[type][format].push_back(textures[i]); + } + } + } + + /*if (immediate) { LLImageGL::deleteDeadTextures(); - } + }*/ } // static @@ -1162,10 +1225,11 @@ BOOL LLImageGL::createGLTexture() if(mTexName) { - glDeleteTextures(1, (reinterpret_cast(&mTexName))) ; + LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, (reinterpret_cast(&mTexName))) ; } - glGenTextures(1, (GLuint*)&mTexName); + + LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName); stop_glerror(); if (!mTexName) { @@ -1279,7 +1343,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } else { - LLImageGL::generateTextures(1, &mTexName); + LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName); stop_glerror(); { llverify(gGL.getTexUnit(0)->bind(this)); @@ -1329,7 +1393,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ decTextureCounter(mTextureMemory, mComponents, mCategory) ; } - LLImageGL::deleteTextures(1, &old_name); + LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, &old_name); stop_glerror(); } @@ -1345,59 +1409,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ mLastBindTime = sLastFrameTime; return TRUE; } -#if 0 -BOOL LLImageGL::setDiscardLevel(S32 discard_level) -{ - llassert(discard_level >= 0); - llassert(mCurrentDiscardLevel >= 0); - - discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - - if (mDontDiscard) - { - // don't discard! - return FALSE; - } - else if (discard_level == mCurrentDiscardLevel) - { - // nothing to do - return FALSE; - } - else if (discard_level < mCurrentDiscardLevel) - { - // larger image - dump(); - llerrs << "LLImageGL::setDiscardLevel() called with larger discard level; use createGLTexture()" << llendl; - return FALSE; - } - else if (mUseMipMaps) - { - LLPointer imageraw = new LLImageRaw; - while(discard_level > mCurrentDiscardLevel) - { - if (readBackRaw(discard_level, imageraw, false)) - { - break; - } - discard_level--; - } - if (discard_level == mCurrentDiscardLevel) - { - // unable to increase the discard level - return FALSE; - } - return createGLTexture(discard_level, imageraw); - } - else - { -#if !LL_LINUX && !LL_SOLARIS - // *FIX: This should not be skipped for the linux client. - llerrs << "LLImageGL::setDiscardLevel() called on image without mipmaps" << llendl; -#endif - return FALSE; - } -} -#endif BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) { @@ -1408,6 +1419,8 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre if (discard_level < 0) { discard_level = mCurrentDiscardLevel; + if(discard_level < 0) + return FALSE; } if (mTexName == 0 || discard_level < mCurrentDiscardLevel || discard_level > mMaxDiscardLevel ) @@ -1515,28 +1528,32 @@ void LLImageGL::deleteDeadTextures() { bool reset = false; - while (!sDeadTextureList.empty()) + for(U32 i=0;igetCurrTexture() == tex) + while(!it->second.empty()) { - tex_unit->unbind(tex_unit->getCurrType()); - stop_glerror(); - - if (i > 0) + GLuint tex = it->second.front(); + it->second.pop_front(); + for (int j = 0; j < gGLManager.mNumTextureImageUnits; j++) { - reset = true; + LLTexUnit* tex_unit = gGL.getTexUnit(j); + if (tex_unit && tex_unit->getCurrTexture() == tex) + { + tex_unit->unbind(tex_unit->getCurrType()); + stop_glerror(); + + if (i > 0) + { + reset = true; + } + } } + glDeleteTextures(1, &tex); + stop_glerror(); } } - - glDeleteTextures(1, &tex); - stop_glerror(); } if (reset) @@ -1559,9 +1576,9 @@ void LLImageGL::destroyGLTexture() mTextureMemory = 0; } - LLImageGL::deleteTextures(1, &mTexName); - mTexName = 0; + LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, &mTexName); mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. + mTexName = 0; mGLTextureCreated = FALSE ; } } @@ -1986,6 +2003,7 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) void LLImageGL::setCategory(S32 category) { +#if 0 //turn this off temporarily because it is not in use now. if(!gAuditTexture) { return ; @@ -1996,7 +2014,7 @@ void LLImageGL::setCategory(S32 category) { sTextureMemByCategory[mCategory] -= mTextureMemory ; } - if(category > -1 && category < sMaxCatagories) + if(category > -1 && category < sMaxCategories) { sTextureMemByCategory[category] += mTextureMemory ; mCategory = category; @@ -2006,6 +2024,7 @@ void LLImageGL::setCategory(S32 category) mCategory = -1 ; } } +#endif } //for debug use diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 37b997199..a80dd0998 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -2,31 +2,25 @@ * @file llimagegl.h * @brief Object for managing images and their textures * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -51,8 +45,16 @@ class LLImageGL : public LLRefCount { friend class LLTexUnit; public: - static std::list sDeadTextureList; + static U32 sCurTexName; + //previously used but now available texture names + // sDeadTextureList[][] + typedef std::map > dead_texturelist_t; + static dead_texturelist_t sDeadTextureList[LLTexUnit::TT_NONE]; + + // These 2 functions replace glGenTextures() and glDeleteTextures() + static void generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures); + static void deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip_levels, S32 numTextures, U32 *textures, bool immediate = false); static void deleteDeadTextures(); // Size calculation @@ -102,15 +104,11 @@ public: void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;} void setAllowCompression(bool allow) { mAllowCompression = allow; } - // These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D() - // for tracking purposes and will be deprecated in the future - static void generateTextures(S32 numTextures, U32 *textures); - static void deleteTextures(S32 numTextures, U32 *textures, bool immediate = false); static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true); BOOL createGLTexture() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, - S32 category = sMaxCatagories - 1); + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, + S32 category = sMaxCategories-1); BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); void setImage(const LLImageRaw* imageraw); void setImage(const U8* data_in, BOOL data_hasmips = FALSE); @@ -185,6 +183,7 @@ public: private: LLPointer mSaveData; // used for destroyGL/restoreGL + S32 mSaveDiscardLevel; U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel U16 mPickMaskWidth; U16 mPickMaskHeight; @@ -209,7 +208,8 @@ protected: LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) bool mHasMipMaps; - + S32 mMipLevels; + LLGLboolean mIsResident; S8 mComponents; @@ -232,8 +232,6 @@ public: static F32 sLastFrameTime; - static LLGLuint sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS]; // Currently bound texture ID - // Global memory statistics static S32 sGlobalTextureMemoryInBytes; // Tracks main memory texmem static S32 sBoundTextureMemoryInBytes; // Tracks bound texmem for last completed frame @@ -255,7 +253,7 @@ public: static void initClass(S32 num_catagories) ; static void cleanupClass() ; private: - static S32 sMaxCatagories ; + static S32 sMaxCategories ; //the flag to allow to call readBackRaw(...). //can be removed if we do not use that function at all. diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 5c0c8f6a7..d73b17a51 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -422,12 +422,14 @@ void LLTexUnit::unbind(eTextureType type) if (mIndex < 0) return; + //always flush and activate for consistency + // some code paths assume unbind always flushes and sets the active texture + gGL.flush(); + activate(); + // Disabled caching of binding state. if (mCurrTexType == type) { - gGL.flush(); - - activate(); mCurrTexture = 0; if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE) { @@ -478,11 +480,25 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio } else if (option >= TFO_BILINEAR) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + if (mHasMipMaps) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + } + else + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } } else { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + if (mHasMipMaps) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + } + else + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } } if (gGLManager.mHasAnisotropic) @@ -1440,6 +1456,8 @@ void LLRender::loadIdentity() flush(); { + llassert_always(mMatrixMode < NUM_MATRIX_MODES) ; + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity(); mMatHash[mMatrixMode]++; } @@ -1687,7 +1705,7 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, LLTexUnit* LLRender::getTexUnit(U32 index) { - if ((index >= 0) && (index < mTexUnits.size())) + if (index < mTexUnits.size()) { return mTexUnits[index]; } diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 324a6accc..6ea20e977 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -61,7 +61,6 @@ bool LLRenderTarget::sUseFBO = false; LLRenderTarget::LLRenderTarget() : mResX(0), mResY(0), - mTex(0), mFBO(0), mDepth(0), mStencil(0), @@ -149,7 +148,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) } U32 tex; - LLImageGL::generateTextures(1, &tex); + LLImageGL::generateTextures(mUsage, color_fmt, 1, &tex); gGL.getTexUnit(0)->bindManual(mUsage, tex); stop_glerror(); @@ -207,6 +206,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) } mTex.push_back(tex); + mInternalFormat.push_back(color_fmt); if (gDebugGL) { //bind and unbind to validate target @@ -231,7 +231,7 @@ bool LLRenderTarget::allocateDepth() } else { - LLImageGL::generateTextures(1, &mDepth); + LLImageGL::generateTextures(mUsage, GL_DEPTH_COMPONENT24, 1, &mDepth); gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); @@ -308,7 +308,7 @@ void LLRenderTarget::release() } else { - LLImageGL::deleteTextures(1, &mDepth, true); + LLImageGL::deleteTextures(mUsage, 0, 0, 1, &mDepth, true); stop_glerror(); } mDepth = 0; @@ -340,8 +340,9 @@ void LLRenderTarget::release() if (mTex.size() > 0) { sBytesAllocated -= mResX*mResY*4*mTex.size(); - LLImageGL::deleteTextures(mTex.size(), &mTex[0], true); + LLImageGL::deleteTextures(mUsage, mInternalFormat[0], 0, mTex.size(), &mTex[0], true); mTex.clear(); + mInternalFormat.clear(); } mResX = mResY = 0; @@ -645,7 +646,7 @@ void LLMultisampleBuffer::release() if (mTex.size() > 0) { - sBytesAllocated -= mResX*mResY*4*mResX*mResY*4*mTex.size(); + sBytesAllocated -= mResX*mResY*4*mTex.size(); glDeleteRenderbuffers(mTex.size(), (GLuint *) &mTex[0]); mTex.clear(); diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 4051b3e9b..9ed95770e 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -152,6 +152,7 @@ protected: U32 mResX; U32 mResY; std::vector mTex; + std::vector mInternalFormat; U32 mFBO; U32 mDepth; bool mStencil; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index b6238ab01..0c17fbfb5 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -718,20 +718,33 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } else if (major_version > 1 || minor_version >= 30) { //switches are supported in GLSL 1.30 and later - text[count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n"); - text[count++] = strdup("\tswitch (vary_texture_index.r)\n"); - text[count++] = strdup("\t{\n"); - - //switch body - for (S32 i = 0; i < texture_index_channels; ++i) - { - std::string case_str = llformat("\t\tcase %d: ret = texture2D(tex%d, texcoord); break;\n", i, i); - text[count++] = strdup(case_str.c_str()); + if (gGLManager.mIsNVIDIA) + { //switches are unreliable on some NVIDIA drivers + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string if_string = llformat("\t%sif (vary_texture_index.r == %d) { return texture2D(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i); + text[count++] = strdup(if_string.c_str()); + } + text[count++] = strdup("\treturn vec4(1,0,1,1);\n"); + text[count++] = strdup("}\n"); } + else + { + text[count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n"); + text[count++] = strdup("\tswitch (vary_texture_index.r)\n"); + text[count++] = strdup("\t{\n"); + + //switch body + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string case_str = llformat("\t\tcase %d: ret = texture2D(tex%d, texcoord); break;\n", i, i); + text[count++] = strdup(case_str.c_str()); + } - text[count++] = strdup("\t}\n"); - text[count++] = strdup("\treturn ret;\n"); - text[count++] = strdup("}\n"); + text[count++] = strdup("\t}\n"); + text[count++] = strdup("\treturn ret;\n"); + text[count++] = strdup("}\n"); + } } else { //should never get here. Indexed texture rendering requires GLSL 1.30 or later @@ -1069,6 +1082,9 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("size"); mReservedUniforms.push_back("falloff"); + mReservedUniforms.push_back("box_center"); + mReservedUniforms.push_back("box_size"); + mReservedUniforms.push_back("minLuminance"); mReservedUniforms.push_back("maxExtractAlpha"); @@ -1105,8 +1121,9 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("proj_shadow_res"); mReservedUniforms.push_back("depth_cutoff"); mReservedUniforms.push_back("norm_cutoff"); + mReservedUniforms.push_back("shadow_target_width"); - llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_NORM_CUTOFF+1); + llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1); mReservedUniforms.push_back("tc_scale"); mReservedUniforms.push_back("rcp_screen_res"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 8c54628c3..b06d61b3e 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -97,6 +97,8 @@ public: LIGHT_CENTER, LIGHT_SIZE, LIGHT_FALLOFF, + BOX_CENTER, + BOX_SIZE, GLOW_MIN_LUMINANCE, GLOW_MAX_EXTRACT_ALPHA, @@ -130,6 +132,7 @@ public: DEFERRED_PROJ_SHADOW_RES, DEFERRED_DEPTH_CUTOFF, DEFERRED_NORM_CUTOFF, + DEFERRED_SHADOW_TARGET_WIDTH, FXAA_TC_SCALE, FXAA_RCP_SCREEN_RES, diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 8dd24da14..bc4c201d9 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -101,7 +101,7 @@ U32 LLVertexBuffer::sSetCount = 0; S32 LLVertexBuffer::sCount = 0; S32 LLVertexBuffer::sGLCount = 0; S32 LLVertexBuffer::sMappedCount = 0; -bool LLVertexBuffer::sDisableVBOMapping = false; +bool LLVertexBuffer::sDisableVBOMapping = true; //Temporary workaround for vbo mapping being straight up broken bool LLVertexBuffer::sEnableVBOs = true; U32 LLVertexBuffer::sGLRenderBuffer = 0; U32 LLVertexBuffer::sGLRenderArray = 0; @@ -116,60 +116,6 @@ bool LLVertexBuffer::sUseStreamDraw = true; bool LLVertexBuffer::sUseVAO = false; bool LLVertexBuffer::sPreferStreamDraw = false; -const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms - -class LLGLSyncFence : public LLGLFence -{ -public: -#ifdef GL_ARB_sync - GLsync mSync; -#endif - - LLGLSyncFence() - { -#ifdef GL_ARB_sync - mSync = 0; -#endif - } - - virtual ~LLGLSyncFence() - { -#ifdef GL_ARB_sync - if (mSync) - { - glDeleteSync(mSync); - } -#endif - } - - void placeFence() - { -#ifdef GL_ARB_sync - if (mSync) - { - glDeleteSync(mSync); - } - mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); -#endif - } - - void wait() - { -#ifdef GL_ARB_sync - if (mSync) - { - while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED) - { //track the number of times we've waited here - static S32 waits = 0; - waits++; - } - } -#endif - } - - -}; - volatile U8* LLVBOPool::allocate(U32& name, U32 size) { @@ -792,7 +738,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping) { sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject; - sDisableVBOMapping = sEnableVBOs && no_vbo_mapping; + sDisableVBOMapping = sEnableVBOs;// && no_vbo_mapping; //Temporary workaround for vbo mapping being straight up broken if (!sPrivatePoolp) { @@ -1208,20 +1154,15 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) llassert(nverts >= 0); - if (nverts >= 65535) + if (nverts > 65536) { - // FIRE-5077; Just print an info if there are more than 0xFFFF, for now just so there is a message in the logs where in older version #vertices would have been capped. - - // llwarns << "Vertex buffer overflow!" << llendl; - // nverts = 65535; - llinfos << "More vertices than 65535 (#" << nverts << ")" < + llwarns << "Vertex buffer overflow!" << llendl; + nverts = 65536; } - S32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts); + U32 needed_size = (U32)calcOffsets(mTypeMask, mOffsets, nverts); - if (needed_size > mSize || needed_size <= mSize/2) + if (needed_size > (U32)mSize || needed_size <= (U32)mSize/2) { createGLBuffer(needed_size); } @@ -1237,9 +1178,9 @@ void LLVertexBuffer::updateNumIndices(S32 nindices) llassert(nindices >= 0); - S32 needed_size = sizeof(U16) * nindices; + U32 needed_size = sizeof(U16) * (U32)nindices; - if (needed_size > mIndicesSize || needed_size <= mIndicesSize/2) + if (needed_size > (U32)mIndicesSize || needed_size <= (U32)mIndicesSize/2) { createGLIndices(needed_size); } @@ -1255,21 +1196,11 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) stop_glerror(); - // FIRE-5077; Just print an info if there are more than 0xFFFF, for now just so there is a message in the logs where in older version #vertices would have been capped. - - // if (nverts < 0 || nindices < 0 || - // nverts > 65536) - // { - // llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl; - // } - - if( nverts < 0 || nindices < 0 ) - llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl; - - if( nverts > 0xFFFF ) - llinfos << "More vertices than 65535 (#" << nverts << ")" < + if (nverts < 0 || nindices < 0 || + nverts > 65536) + { + llwarns << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl; + } updateNumVerts(nverts); updateNumIndices(nindices); @@ -1387,13 +1318,13 @@ void LLVertexBuffer::setupVertexArray() //glVertexattribIPointer requires GLSL 1.30 or later if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) { - glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], (void*) mOffsets[i]); + glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], reinterpret_cast(mOffsets[i])); } #endif } else { - glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], (void*) mOffsets[i]); + glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], reinterpret_cast(mOffsets[i])); } } else @@ -2303,10 +2234,10 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) stop_glerror(); volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; - /*if ((data_mask & mTypeMask) != data_mask) + if (gDebugGL && ((data_mask & mTypeMask) != data_mask)) { llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; - }*/ + } if (LLGLSLShader::sNoFixedFunction) { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index ceaa70c3b..469acfcef 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -85,12 +85,6 @@ public: std::vector mFreeList; }; -class LLGLFence -{ -public: - virtual void placeFence() = 0; - virtual void wait() = 0; -}; //============================================================================ // base class diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 42fa88495..92a54d021 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -5,22 +5,26 @@ project(llui) include(00-Common) include(LLCommon) include(LLImage) +include(LLInventory) include(LLMath) include(LLMessage) include(LLRender) include(LLWindow) include(LLVFS) include(LLXML) +include(LLXUIXML) include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS} + ${LLINVENTORY_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} + ${LLXUIXML_INCLUDE_DIRS} ) set(llui_SOURCE_FILES @@ -75,6 +79,7 @@ set(llui_SOURCE_FILES lluistring.cpp llundo.cpp llviewborder.cpp + llviewmodel.cpp llview.cpp llviewquery.cpp ) @@ -142,6 +147,7 @@ set(llui_HEADER_FILES lluixmltags.h llundo.h llviewborder.h + llviewmodel.h llview.h llviewquery.h ) @@ -159,6 +165,7 @@ target_link_libraries(llui llwindow llimage llvfs # ugh, just for LLDir + llxuixml llxml llcommon # must be after llimage, llwindow, llrender llmath diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index c4bdbfc4a..f10e211f1 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -63,47 +63,64 @@ S32 BORDER_SIZE = 1; LLButton::LLButton( const std::string& name, const LLRect& rect, const std::string& control_name, void (*click_callback)(void*), void *callback_data) : LLUICtrl(name, rect, TRUE, NULL, NULL), - mClickedCallback( click_callback ), - mMouseDownCallback( NULL ), - mMouseUpCallback( NULL ), - mHeldDownCallback( NULL ), - mGLFont( NULL ), + mMouseDownFrame( 0 ), - mHeldDownDelay( 0.5f ), // seconds until held-down callback is called - mHeldDownFrameDelay( 0 ), - mImageUnselected( NULL ), - mImageSelected( NULL ), - mImageHoverSelected( NULL ), - mImageHoverUnselected( NULL ), - mImageDisabled( NULL ), - mImageDisabledSelected( NULL ), - mToggleState( FALSE ), - mIsToggle( FALSE ), - mScaleImage( TRUE ), - mDropShadowedText( TRUE ), + mMouseHeldDownCount(0), mBorderEnabled( FALSE ), mFlashing( FALSE ), + mCurGlowStrength(0.f), + mNeedsHighlight(FALSE), + mUnselectedLabel(name), + mSelectedLabel(name), + mGLFont( LLFontGL::getFontSansSerif() ), + mHeldDownDelay( 0.5f ), // seconds until held-down callback is called + mHeldDownFrameDelay( 0 ), + mImageUnselected(LLUI::getUIImage("button_enabled_32x128.tga")), + mImageSelected(LLUI::getUIImage("button_enabled_selected_32x128.tga")), + mImageDisabled(LLUI::getUIImage("button_disabled_32x128.tga")), + mImageDisabledSelected(LLUI::getUIImage("button_disabled_32x128.tga")), + mImagePressed(LLUI::getUIImage("button_enabled_selected_32x128.tga")), + mImagePressedSelected(LLUI::getUIImage("button_enabled_32x128.tga")), + mImageFlash(NULL), + mImageHoverSelected( NULL ), + mImageHoverUnselected( NULL ), + mUnselectedLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelColor" )), + mSelectedLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelSelectedColor")), + mDisabledLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelDisabledColor")), + mDisabledSelectedLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelSelectedDisabledColor")), + mImageColor(LLUI::sColorsGroup->getColor("ButtonImageColor")), + mFlashBgColor(LLUI::sColorsGroup->getColor("ButtonFlashBgColor")), + mDisabledImageColor(LLUI::sColorsGroup->getColor("ButtonImageColor")), + mImageOverlay(NULL), + mImageOverlayColor(LLColor4::white), + mImageOverlayDisabledColor(LLColor4(1.f,1.f,1.f,.5f)), + mImageOverlaySelectedColor(LLColor4::white), + mImageOverlayAlignment(LLFontGL::HCENTER), + mImageOverlayTopPad(0), + mImageOverlayBottomPad(0), + mImgOverlayLabelSpace(1), + mIsToggle( FALSE ), + mScaleImage( TRUE ), + mDropShadowedText( TRUE ), + mAutoResize( FALSE ), mHAlign( LLFontGL::HCENTER ), mLeftHPad( LLBUTTON_H_PAD ), mRightHPad( LLBUTTON_H_PAD ), - mHoverGlowStrength(0.15f), - mCurGlowStrength(0.f), - mNeedsHighlight(FALSE), + mBottomVPad( LLBUTTON_V_PAD ), + mHoverGlowStrength(0.25f), mCommitOnReturn(TRUE), - mImagep( NULL ) + mFadeWhenDisabled(FALSE), + mForcePressedState(false), + mDisplayPressedState(TRUE), + mMouseDownSignal(NULL), + mMouseUpSignal(NULL), + mHeldDownSignal(NULL), + mHandleRightMouse(false), + mButtonFlashCount(LLUI::sConfigGroup->getS32("ButtonFlashCount")), + mButtonFlashRate(LLUI::sConfigGroup->getF32("ButtonFlashRate")), + mAlpha(1.f) { - mUnselectedLabel = name; - mSelectedLabel = name; - - setImageUnselected(std::string("button_enabled_32x128.tga")); - setImageSelected(std::string("button_enabled_selected_32x128.tga")); - setImageDisabled(std::string("button_disabled_32x128.tga")); - setImageDisabledSelected(std::string("button_disabled_32x128.tga")); - - mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); - mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); - - init(click_callback, callback_data, NULL, control_name); + init(click_callback, callback_data, control_name); } @@ -117,79 +134,92 @@ LLButton::LLButton(const std::string& name, const LLRect& rect, const std::string& unselected_label, const std::string& selected_label ) : LLUICtrl(name, rect, TRUE, NULL, NULL), - mClickedCallback( click_callback ), - mMouseDownCallback( NULL ), - mMouseUpCallback( NULL ), - mHeldDownCallback( NULL ), - mGLFont( NULL ), mMouseDownFrame( 0 ), + mMouseHeldDownCount(0), + mBorderEnabled( FALSE ), + mFlashing( FALSE ), + mCurGlowStrength(0.f), + mNeedsHighlight(FALSE), + mUnselectedLabel(unselected_label), + mSelectedLabel(selected_label), + mGLFont( font ? font : LLFontGL::getFontSansSerif() ), mHeldDownDelay( 0.5f ), // seconds until held-down callback is called mHeldDownFrameDelay( 0 ), - mImageUnselected( NULL ), - mImageSelected( NULL ), + mImageUnselected(LLUI::getUIImage("button_enabled_32x128.tga")), + mImageSelected(LLUI::getUIImage("button_enabled_selected_32x128.tga")), + mImageDisabled(LLUI::getUIImage("button_disabled_32x128.tga")), + mImageDisabledSelected(LLUI::getUIImage("button_disabled_32x128.tga")), + mImagePressed(LLUI::getUIImage("button_enabled_selected_32x128.tga")), + mImagePressedSelected(LLUI::getUIImage("button_enabled_32x128.tga")), + mImageFlash(NULL), mImageHoverSelected( NULL ), mImageHoverUnselected( NULL ), - mImageDisabled( NULL ), - mImageDisabledSelected( NULL ), - mToggleState( FALSE ), + mUnselectedLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelColor" )), + mSelectedLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelSelectedColor")), + mDisabledLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelDisabledColor")), + mDisabledSelectedLabelColor(LLUI::sColorsGroup->getColor("ButtonLabelSelectedDisabledColor")), + mImageColor(LLUI::sColorsGroup->getColor("ButtonImageColor")), + mFlashBgColor(LLUI::sColorsGroup->getColor("ButtonFlashBgColor")), + mDisabledImageColor(LLUI::sColorsGroup->getColor("ButtonImageColor")), + mImageOverlay(NULL), + mImageOverlayColor(LLColor4::white), + mImageOverlayDisabledColor(LLColor4(1.f,1.f,1.f,.5f)), + mImageOverlaySelectedColor(LLColor4::white), + mImageOverlayAlignment(LLFontGL::HCENTER), + mImageOverlayTopPad(0), + mImageOverlayBottomPad(0), + mImgOverlayLabelSpace(1), mIsToggle( FALSE ), mScaleImage( TRUE ), mDropShadowedText( TRUE ), - mBorderEnabled( FALSE ), - mFlashing( FALSE ), + mAutoResize( FALSE ), mHAlign( LLFontGL::HCENTER ), mLeftHPad( LLBUTTON_H_PAD ), mRightHPad( LLBUTTON_H_PAD ), + mBottomVPad( LLBUTTON_V_PAD ), mHoverGlowStrength(0.25f), - mCurGlowStrength(0.f), - mNeedsHighlight(FALSE), mCommitOnReturn(TRUE), - mImagep( NULL ) + mFadeWhenDisabled(FALSE), + mForcePressedState(false), + mDisplayPressedState(TRUE), + mMouseDownSignal(NULL), + mMouseUpSignal(NULL), + mHeldDownSignal(NULL), + mHandleRightMouse(false), + mButtonFlashCount(LLUI::sConfigGroup->getS32("ButtonFlashCount")), + mButtonFlashRate(LLUI::sConfigGroup->getF32("ButtonFlashRate")), + mAlpha(1.f) { - mUnselectedLabel = unselected_label; - mSelectedLabel = selected_label; - - // by default, disabled color is same as enabled - mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); - mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); if( unselected_image_name != "" ) { // user-specified image - don't use fixed borders unless requested - setImageUnselected(unselected_image_name); - setImageDisabled(unselected_image_name); + mImageUnselected = LLUI::getUIImage(unselected_image_name); + mImageDisabled = mImageUnselected; - mDisabledImageColor.mV[VALPHA] = 0.5f; - mScaleImage = FALSE; - } - else - { - setImageUnselected(std::string("button_enabled_32x128.tga")); - setImageDisabled(std::string("button_disabled_32x128.tga")); + mFadeWhenDisabled = TRUE; + //mScaleImage = FALSE; + + mImagePressedSelected = mImageUnselected; } if( selected_image_name != "" ) { // user-specified image - don't use fixed borders unless requested - setImageSelected(selected_image_name); - setImageDisabledSelected(selected_image_name); + mImageSelected = LLUI::getUIImage(selected_image_name); + mImageDisabledSelected = mImageSelected; - mDisabledImageColor.mV[VALPHA] = 0.5f; - mScaleImage = FALSE; - } - else - { - setImageSelected(std::string("button_enabled_selected_32x128.tga")); - setImageDisabledSelected(std::string("button_disabled_32x128.tga")); + mFadeWhenDisabled = TRUE; + //mScaleImage = FALSE; + + mImagePressed = mImageSelected; } - init(click_callback, callback_data, font, control_name); + init(click_callback, callback_data, control_name); } -void LLButton::init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const std::string& control_name) +void LLButton::init(void (*click_callback)(void*), void *callback_data, const std::string& control_name) { - mGLFont = ( font ? font : LLFontGL::getFontSansSerif()); - // Hack to make sure there is space for at least one character if (getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" "))) { @@ -198,30 +228,22 @@ void LLButton::init(void (*click_callback)(void*), void *callback_data, const LL mRightHPad = LLBUTTON_ORIG_H_PAD; } - mCallbackUserData = callback_data; mMouseDownTimer.stop(); - + + if(click_callback) + setClickedCallback(click_callback, callback_data); + setControlName(control_name, NULL); - mUnselectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelColor" ) ); - mSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedColor" ) ); - mDisabledLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelDisabledColor" ) ); - mDisabledSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedDisabledColor" ) ); - mHighlightColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedFgColor" ) ); - mUnselectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedBgColor" ) ); - mSelectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonSelectedBgColor" ) ); - mFlashBgColor = ( LLUI::sColorsGroup->getColor( "ButtonFlashBgColor" ) ); - - mImageOverlayAlignment = LLFontGL::HCENTER; - mImageOverlayColor = LLColor4::white; } + +// virtual LLButton::~LLButton() { - if( hasMouseCapture() ) - { - gFocusMgr.setMouseCapture( NULL ); - } + delete mMouseDownSignal; + delete mMouseUpSignal; + delete mHeldDownSignal; } // HACK: Committing a button is the same as instantly clicking it. @@ -229,19 +251,12 @@ LLButton::~LLButton() void LLButton::onCommit() { // WARNING: Sometimes clicking a button destroys the floater or - // panel containing it. Therefore we need to call mClickedCallback + // panel containing it. Therefore we need to call LLUICtrl::onCommit() // LAST, otherwise this becomes deleted memory. - LLUICtrl::onCommit(); - if (mMouseDownCallback) - { - (*mMouseDownCallback)(mCallbackUserData); - } + if (mMouseDownSignal) (*mMouseDownSignal)(this, LLSD()); - if (mMouseUpCallback) - { - (*mMouseUpCallback)(mCallbackUserData); - } + if (mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); if (getSoundFlags() & MOUSE_DOWN) { @@ -259,13 +274,65 @@ void LLButton::onCommit() } // do this last, as it can result in destroying this button - if (mClickedCallback) - { - (*mClickedCallback)( mCallbackUserData ); - } + LLUICtrl::onCommit(); +} + +/*boost::signals2::connection LLButton::setClickedCallback(const CommitCallbackParam& cb) +{ + return setClickedCallback(initCommitCallback(cb)); +} +boost::signals2::connection LLButton::setMouseDownCallback(const CommitCallbackParam& cb) +{ + return setMouseDownCallback(initCommitCallback(cb)); +} +boost::signals2::connection LLButton::setMouseUpCallback(const CommitCallbackParam& cb) +{ + return setMouseUpCallback(initCommitCallback(cb)); +} +boost::signals2::connection LLButton::setHeldDownCallback(const CommitCallbackParam& cb) +{ + return setHeldDownCallback(initCommitCallback(cb)); +}*/ + + +boost::signals2::connection LLButton::setClickedCallback( const commit_signal_t::slot_type& cb ) +{ + return LLUICtrl::setCommitCallback(cb); +} +boost::signals2::connection LLButton::setMouseDownCallback( const commit_signal_t::slot_type& cb ) +{ + if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t(); + return mMouseDownSignal->connect(cb); +} +boost::signals2::connection LLButton::setMouseUpCallback( const commit_signal_t::slot_type& cb ) +{ + if (!mMouseUpSignal) mMouseUpSignal = new commit_signal_t(); + return mMouseUpSignal->connect(cb); +} +boost::signals2::connection LLButton::setHeldDownCallback( const commit_signal_t::slot_type& cb ) +{ + if (!mHeldDownSignal) mHeldDownSignal = new commit_signal_t(); + return mHeldDownSignal->connect(cb); } +// *TODO: Deprecate (for backwards compatibility only) +boost::signals2::connection LLButton::setClickedCallback( button_callback_t cb, void* data ) +{ + return setClickedCallback(boost::bind(cb, data)); +} +boost::signals2::connection LLButton::setMouseDownCallback( button_callback_t cb, void* data ) +{ + return setMouseDownCallback(boost::bind(cb, data)); +} +boost::signals2::connection LLButton::setMouseUpCallback( button_callback_t cb, void* data ) +{ + return setMouseUpCallback(boost::bind(cb, data)); +} +boost::signals2::connection LLButton::setHeldDownCallback( button_callback_t cb, void* data ) +{ + return setHeldDownCallback(boost::bind(cb, data)); +} BOOL LLButton::handleUnicodeCharHere(llwchar uni_char) { @@ -278,10 +345,8 @@ BOOL LLButton::handleUnicodeCharHere(llwchar uni_char) toggleState(); } - if (mClickedCallback) - { - (*mClickedCallback)( mCallbackUserData ); - } + LLUICtrl::onCommit(); + handled = TRUE; } return handled; @@ -299,10 +364,7 @@ BOOL LLButton::handleKeyHere(KEY key, MASK mask ) handled = TRUE; - if (mClickedCallback) - { - (*mClickedCallback)( mCallbackUserData ); - } + LLUICtrl::onCommit(); } return handled; } @@ -310,27 +372,35 @@ BOOL LLButton::handleKeyHere(KEY key, MASK mask ) BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) { - // Route future Mouse messages here preemptively. (Release on mouse up.) - gFocusMgr.setMouseCapture( this ); - - if (hasTabStop() && !getIsChrome()) + if (!childrenHandleMouseDown(x, y, mask)) { - setFocus(TRUE); - } + // Route future Mouse messages here preemptively. (Release on mouse up.) + gFocusMgr.setMouseCapture( this ); - if (mMouseDownCallback) - { - (*mMouseDownCallback)(mCallbackUserData); - } + if (hasTabStop() && !getIsChrome()) + { + setFocus(TRUE); + } + + /* + * ATTENTION! This call fires another mouse down callback. + * If you wish to remove this call emit that signal directly + * by calling LLUICtrl::mMouseDownSignal(x, y, mask); + */ + LLUICtrl::handleMouseDown(x, y, mask); + + if(mMouseDownSignal) (*mMouseDownSignal)(this, LLSD()); mMouseDownTimer.start(); - mMouseDownFrame = (S32) LLFrameTimer::getFrameCount(); - - if (getSoundFlags() & MOUSE_DOWN) - { - make_ui_sound("UISndClick"); - } + mMouseDownFrame = (S32) LLFrameTimer::getFrameCount(); + mMouseHeldDownCount = 0; + + if (getSoundFlags() & MOUSE_DOWN) + { + make_ui_sound("UISndClick"); + } + } return TRUE; } @@ -343,14 +413,17 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) // Always release the mouse gFocusMgr.setMouseCapture( NULL ); - // Regardless of where mouseup occurs, handle callback - if (mMouseUpCallback) - { - (*mMouseUpCallback)(mCallbackUserData); - } + /* + * ATTENTION! This call fires another mouse up callback. + * If you wish to remove this call emit that signal directly + * by calling LLUICtrl::mMouseUpSignal(x, y, mask); + */ + LLUICtrl::handleMouseUp(x, y, mask); - mMouseDownTimer.stop(); - mMouseDownTimer.reset(); + // Regardless of where mouseup occurs, handle callback + if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); + + resetMouseDownTimer(); // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked. // If mouseup in the widget, it's been clicked @@ -366,83 +439,167 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) toggleState(); } - if (mClickedCallback) - { - (*mClickedCallback)( mCallbackUserData ); - } + LLUICtrl::onCommit(); } } + else + { + childrenHandleMouseUp(x, y, mask); + } return TRUE; } +BOOL LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + if (mHandleRightMouse && !childrenHandleRightMouseDown(x, y, mask)) + { + // Route future Mouse messages here preemptively. (Release on mouse up.) + gFocusMgr.setMouseCapture( this ); + + if (hasTabStop() && !getIsChrome()) + { + setFocus(TRUE); + } + +// if (pointInView(x, y)) +// { +// } + // send the mouse down signal + LLUICtrl::handleRightMouseDown(x,y,mask); + // *TODO: Return result of LLUICtrl call above? Should defer to base class + // but this might change the mouse handling of existing buttons in a bad way + // if they are not mouse opaque. + } + + return TRUE; +} + +BOOL LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask) +{ + if (mHandleRightMouse) + { + // We only handle the click if the click both started and ended within us + if( hasMouseCapture() ) + { + // Always release the mouse + gFocusMgr.setMouseCapture( NULL ); + + // if (pointInView(x, y)) + // { + // mRightMouseUpSignal(this, x,y,mask); + // } + } + else + { + childrenHandleRightMouseUp(x, y, mask); + } + + // send the mouse up signal + LLUICtrl::handleRightMouseUp(x,y,mask); + // *TODO: Return result of LLUICtrl call above? Should defer to base class + // but this might change the mouse handling of existing buttons in a bad way. + // if they are not mouse opaque. + } + return TRUE; +} + +void LLButton::setHighlight(bool b) +{ + mNeedsHighlight = b; +} BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) { - LLMouseHandler* other_captor = gFocusMgr.getMouseCapture(); - mNeedsHighlight = other_captor == NULL || - other_captor == this || - // this following bit is to support modal dialogs - (other_captor->isView() && hasAncestor((LLView*)other_captor)); + if (isInEnabledChain() + && (!gFocusMgr.getMouseCapture() || gFocusMgr.getMouseCapture() == this)) + mNeedsHighlight = TRUE; - if (mMouseDownTimer.getStarted() && NULL != mHeldDownCallback) + if (!childrenHandleHover(x, y, mask)) { - F32 elapsed = getHeldDownTime(); - if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= (S32)LLFrameTimer::getFrameCount() - mMouseDownFrame) + if (mMouseDownTimer.getStarted()) { - mHeldDownCallback( mCallbackUserData ); + F32 elapsed = getHeldDownTime(); + if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= (S32)LLFrameTimer::getFrameCount() - mMouseDownFrame) + { + LLSD param; + param["count"] = mMouseHeldDownCount++; + if (mHeldDownSignal) (*mHeldDownSignal)(this, param); + } } + + // We only handle the click if the click both started and ended within us + getWindow()->setCursor(UI_CURSOR_ARROW); + lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; } - - // We only handle the click if the click both started and ended within us - getWindow()->setCursor(UI_CURSOR_ARROW); - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; - return TRUE; } +void LLButton::getOverlayImageSize(S32& overlay_width, S32& overlay_height) +{ + overlay_width = mImageOverlay->getWidth(); + overlay_height = mImageOverlay->getHeight(); + + F32 scale_factor = llmin((F32)getRect().getWidth() / (F32)overlay_width, (F32)getRect().getHeight() / (F32)overlay_height, 1.f); + overlay_width = llround((F32)overlay_width * scale_factor); + overlay_height = llround((F32)overlay_height * scale_factor); +} + // virtual void LLButton::draw() { - BOOL flash = FALSE; + F32 alpha = mAlpha; + bool flash = FALSE; if( mFlashing ) { F32 elapsed = mFlashingTimer.getElapsedTimeF32(); - S32 flash_count = S32(elapsed * LLUI::sConfigGroup->getF32("ButtonFlashRate") * 2.f); + S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f); // flash on or off? - flash = (flash_count % 2 == 0) || flash_count > S32((F32)LLUI::sConfigGroup->getS32("ButtonFlashCount") * 2.f); + flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f); } - BOOL pressed_by_keyboard = FALSE; + bool pressed_by_keyboard = FALSE; if (hasFocus()) { pressed_by_keyboard = gKeyboard->getKeyDown(' ') || (mCommitOnReturn && gKeyboard->getKeyDown(KEY_RETURN)); } - // Unselected image assignments - S32 local_mouse_x; - S32 local_mouse_y; - LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); + bool mouse_pressed_and_over = false; + if (hasMouseCapture()) + { + S32 local_mouse_x ; + S32 local_mouse_y; + LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); + mouse_pressed_and_over = pointInView(local_mouse_x, local_mouse_y); + } - BOOL pressed = pressed_by_keyboard - || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y)) - || mToggleState; + bool enabled = isInEnabledChain(); - BOOL use_glow_effect = FALSE; + bool pressed = pressed_by_keyboard + || mouse_pressed_and_over + || mForcePressedState; + bool selected = getToggleState(); + + bool use_glow_effect = FALSE; LLColor4 glow_color = LLColor4::white; LLRender::eBlendType glow_type = LLRender::BT_ADD_WITH_ALPHA; - if ( mNeedsHighlight ) + LLUIImage* imagep = NULL; + if (pressed && mDisplayPressedState) { - if (pressed) + imagep = selected ? mImagePressedSelected : mImagePressed; + } + else if ( mNeedsHighlight ) + { + if (selected) { if (mImageHoverSelected) { - mImagep = mImageHoverSelected; + imagep = mImageHoverSelected; } else { - mImagep = mImageSelected; + imagep = mImageSelected; use_glow_effect = TRUE; } } @@ -450,32 +607,18 @@ void LLButton::draw() { if (mImageHoverUnselected) { - mImagep = mImageHoverUnselected; + imagep = mImageHoverUnselected; } else { - mImagep = mImageUnselected; + imagep = mImageUnselected; use_glow_effect = TRUE; } } } - else if ( pressed ) + else { - mImagep = mImageSelected; - } - else - { - mImagep = mImageUnselected; - } - - if (mFlashing) - { - use_glow_effect = TRUE; - glow_type = LLRender::BT_ALPHA; // blend the glow - if (mNeedsHighlight) // highlighted AND flashing - glow_color = (glow_color*0.5f + mFlashBgColor*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity - else - glow_color = mFlashBgColor; + imagep = selected ? mImageSelected : mImageUnselected; } // Override if more data is available @@ -485,19 +628,41 @@ void LLButton::draw() // disabled but checked if (!mImageDisabledSelected.isNull() && - ( (getEnabled() && getTentative()) - || (!getEnabled() && pressed ) ) ) + ( (enabled && getTentative()) + || (!enabled && selected ) ) ) { - mImagep = mImageDisabledSelected; + imagep = mImageDisabledSelected; } else if (!mImageDisabled.isNull() - && !getEnabled() - && !pressed) + && !enabled + && !selected) { - mImagep = mImageDisabled; + imagep = mImageDisabled; } - if (mNeedsHighlight && !mImagep) + if (mFlashing) + { + // if button should flash and we have icon for flashing, use it as image for button + if(flash && mImageFlash) + { + // setting flash to false to avoid its further influence on glow + flash = false; + imagep = mImageFlash; + } + // else use usual flashing via flash_color + else + { + LLColor4 flash_color = mFlashBgColor.get(); + use_glow_effect = TRUE; + glow_type = LLRender::BT_ALPHA; // blend the glow + if (mNeedsHighlight) // highlighted AND flashing + glow_color = (glow_color*0.5f + flash_color*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity + else + glow_color = flash_color; + } + } + + if (mNeedsHighlight && !imagep) { use_glow_effect = TRUE; } @@ -506,60 +671,37 @@ void LLButton::draw() LLColor4 label_color; // label changes when button state changes, not when pressed - if ( getEnabled() ) + if ( enabled ) { - if ( mToggleState ) + if ( getToggleState() ) { - label_color = mSelectedLabelColor; + label_color = mSelectedLabelColor.get(); } else { - label_color = mUnselectedLabelColor; + label_color = mUnselectedLabelColor.get(); } } else { - if ( mToggleState ) + if ( getToggleState() ) { - label_color = mDisabledSelectedLabelColor; + label_color = mDisabledSelectedLabelColor.get(); } else { - label_color = mDisabledLabelColor; + label_color = mDisabledLabelColor.get(); } } // Unselected label assignments - LLWString label; - - if( mToggleState ) - { - if( getEnabled() || mDisabledSelectedLabel.empty() ) - { - label = mSelectedLabel; - } - else - { - label = mDisabledSelectedLabel; - } - } - else - { - if( getEnabled() || mDisabledLabel.empty() ) - { - label = mUnselectedLabel; - } - else - { - label = mDisabledLabel; - } - } + LLWString label = getCurrentLabel(); // overlay with keyboard focus border if (hasFocus()) { F32 lerp_amt = gFocusMgr.getFocusFlashAmt(); - drawBorder(gFocusMgr.getFocusColor(), llround(lerp(1.f, 3.f, lerp_amt))); + drawBorder(imagep, gFocusMgr.getFocusColor() % alpha, llround(lerp(1.f, 3.f, lerp_amt))); } if (use_glow_effect) @@ -576,25 +718,27 @@ void LLButton::draw() // Draw button image, if available. // Otherwise draw basic rectangular button. - if (mImagep.notNull()) + if (imagep != NULL) { + // apply automatic 50% alpha fade to disabled image + LLColor4 disabled_color = mFadeWhenDisabled ? mDisabledImageColor.get() % 0.5f : mDisabledImageColor.get(); if ( mScaleImage) { - mImagep->draw(getLocalRect(), getEnabled() ? mImageColor : mDisabledImageColor ); + imagep->draw(getLocalRect(), (enabled ? mImageColor.get() : disabled_color) % alpha ); if (mCurGlowStrength > 0.01f) { gGL.setSceneBlendType(glow_type); - mImagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % mCurGlowStrength); + imagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % (mCurGlowStrength * alpha)); gGL.setSceneBlendType(LLRender::BT_ALPHA); } } else { - mImagep->draw(0, 0, getEnabled() ? mImageColor : mDisabledImageColor ); + imagep->draw(0, 0, (enabled ? mImageColor.get() : disabled_color) % alpha ); if (mCurGlowStrength > 0.01f) { gGL.setSceneBlendType(glow_type); - mImagep->drawSolid(0, 0, glow_color % mCurGlowStrength); + imagep->drawSolid(0, 0, glow_color % (mCurGlowStrength * alpha)); gGL.setSceneBlendType(LLRender::BT_ALPHA); } } @@ -602,9 +746,9 @@ void LLButton::draw() else { // no image - llwarns << "No image for button " << getName() << llendl; + lldebugs << "No image for button " << getName() << llendl; // draw it in pink so we can find it - gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1, FALSE); + gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1 % alpha, FALSE); } // let overlay image and text play well together @@ -616,37 +760,41 @@ void LLButton::draw() if (mImageOverlay.notNull() && mImageOverlay->getWidth() > 1) { // get max width and height (discard level 0) - S32 overlay_width = mImageOverlay->getWidth(); - S32 overlay_height = mImageOverlay->getHeight(); + S32 overlay_width; + S32 overlay_height; - F32 scale_factor = llmin((F32)getRect().getWidth() / (F32)overlay_width, (F32)getRect().getHeight() / (F32)overlay_height, 1.f); - overlay_width = llround((F32)overlay_width * scale_factor); - overlay_height = llround((F32)overlay_height * scale_factor); + getOverlayImageSize(overlay_width, overlay_height); S32 center_x = getLocalRect().getCenterX(); S32 center_y = getLocalRect().getCenterY(); //FUGLY HACK FOR "DEPRESSED" BUTTONS - if (pressed) + if (pressed && mDisplayPressedState) { center_y--; center_x++; } + center_y += (mImageOverlayBottomPad - mImageOverlayTopPad); // fade out overlay images on disabled buttons - LLColor4 overlay_color = mImageOverlayColor; - if (!getEnabled()) + LLColor4 overlay_color = mImageOverlayColor.get(); + if (!enabled) { - overlay_color.mV[VALPHA] = 0.5f; + overlay_color = mImageOverlayDisabledColor.get(); } + else if (getToggleState()) + { + overlay_color = mImageOverlaySelectedColor.get(); + } + overlay_color.mV[VALPHA] *= alpha; switch(mImageOverlayAlignment) { case LLFontGL::LEFT: - text_left += overlay_width + 1; - text_width -= overlay_width + 1; + text_left += overlay_width + mImgOverlayLabelSpace; + text_width -= overlay_width + mImgOverlayLabelSpace; mImageOverlay->draw( - mLeftHPad, + mLeftHPad, center_y - (overlay_height / 2), overlay_width, overlay_height, @@ -661,10 +809,10 @@ void LLButton::draw() overlay_color); break; case LLFontGL::RIGHT: - text_right -= overlay_width + 1; - text_width -= overlay_width + 1; + text_right -= overlay_width + mImgOverlayLabelSpace; + text_width -= overlay_width + mImgOverlayLabelSpace; mImageOverlay->draw( - getRect().getWidth() - mRightHPad - overlay_width, + getRect().getWidth() - mRightHPad - overlay_width, center_y - (overlay_height / 2), overlay_width, overlay_height, @@ -698,7 +846,7 @@ void LLButton::draw() S32 y_offset = 2 + (getRect().getHeight() - 20)/2; - if (pressed) + if (pressed && mDisplayPressedState) { y_offset--; x++; @@ -706,8 +854,8 @@ void LLButton::draw() mGLFont->render(label, 0, (F32)x, - (F32)(LLBUTTON_V_PAD + y_offset), - label_color, + (F32)(mBottomVPad + y_offset), + label_color % alpha, mHAlign, LLFontGL::BOTTOM, LLFontGL::NORMAL, mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW, @@ -720,45 +868,45 @@ void LLButton::draw() { drawDebugRect(); } - + // reset hover status for next frame mNeedsHighlight = FALSE; + + LLUICtrl::draw(); } -void LLButton::drawBorder(const LLColor4& color, S32 size) +void LLButton::drawBorder(LLUIImage* imagep, const LLColor4& color, S32 size) { + if (imagep == NULL) return; if (mScaleImage) { - mImagep->drawBorder(getLocalRect(), color, size); + imagep->drawBorder(getLocalRect(), color, size); } else { - mImagep->drawBorder(0, 0, color, size); + imagep->drawBorder(0, 0, color, size); } } -void LLButton::setClickedCallback(void (*cb)(void*), void* userdata) +BOOL LLButton::getToggleState() const { - mClickedCallback = cb; - if (userdata) - { - mCallbackUserData = userdata; - } + return getValue().asBoolean(); } - void LLButton::setToggleState(BOOL b) { - if( b != mToggleState ) + if( b != getToggleState() ) { setControlValue(b); // will fire LLControlVariable callbacks (if any) - mToggleState = b; // may or may not be redundant + setValue(b); // may or may not be redundant + // Unselected label assignments + autoResize(); } } void LLButton::setFlashing( BOOL b ) { - if (b != mFlashing) + if ((bool)b != mFlashing) { mFlashing = b; mFlashingTimer.reset(); @@ -768,18 +916,10 @@ void LLButton::setFlashing( BOOL b ) BOOL LLButton::toggleState() { - setToggleState( !mToggleState ); - return mToggleState; -} + bool flipped = ! getToggleState(); + setToggleState(flipped); -void LLButton::setValue(const LLSD& value ) -{ - mToggleState = value.asBoolean(); -} - -LLSD LLButton::getValue() const -{ - return mToggleState == TRUE; + return flipped; } void LLButton::setLabel( const LLStringExplicit& label ) @@ -806,26 +946,72 @@ void LLButton::setLabelSelected( const LLStringExplicit& label ) mSelectedLabel = label; } -void LLButton::setDisabledLabel( const LLStringExplicit& label ) +const LLUIString& LLButton::getCurrentLabel() const { - mDisabledLabel = label; -} - -void LLButton::setDisabledSelectedLabel( const LLStringExplicit& label ) -{ - mDisabledSelectedLabel = label; + if( getToggleState() ) + { + return mSelectedLabel; + } + else + { + return mUnselectedLabel; + } } void LLButton::setImageUnselected(LLPointer image) { mImageUnselected = image; + if (mImageUnselected.isNull()) + { + llwarns << "Setting default button image for: " << getName() << " to NULL" << llendl; + } } +void LLButton::autoResize() +{ + resize(getCurrentLabel()); +} + +void LLButton::resize(LLUIString label) +{ + // get label length + S32 label_width = mGLFont->getWidth(label.getString()); + // get current btn length + S32 btn_width =getRect().getWidth(); + // check if it need resize + if (mAutoResize) + { + S32 min_width = label_width + mLeftHPad + mRightHPad; + if (mImageOverlay) + { + S32 overlay_width = mImageOverlay->getWidth(); + F32 scale_factor = (getRect().getHeight() - (mImageOverlayBottomPad + mImageOverlayTopPad)) / (F32)mImageOverlay->getHeight(); + overlay_width = llround((F32)overlay_width * scale_factor); + + switch(mImageOverlayAlignment) + { + case LLFontGL::LEFT: + case LLFontGL::RIGHT: + min_width += overlay_width + mImgOverlayLabelSpace; + break; + case LLFontGL::HCENTER: + min_width = llmax(min_width, overlay_width + mLeftHPad + mRightHPad); + break; + default: + // draw nothing + break; + } + } + if (btn_width < min_width) + { + reshape(min_width, getRect().getHeight()); + } + } +} void LLButton::setImages( const std::string &image_name, const std::string &selected_name ) { - setImageUnselected(image_name); - setImageSelected(selected_name); - + setImageUnselected(LLUI::getUIImage(image_name)); + setImageSelected(LLUI::getUIImage(selected_name)); } void LLButton::setImageSelected(LLPointer image) @@ -843,31 +1029,18 @@ void LLButton::setColor(const LLColor4& color) setImageColor(color); } -void LLButton::setAlpha(F32 alpha) -{ - mImageColor.setAlpha(alpha); - mDisabledImageColor.setAlpha(alpha * 0.5f); -} - void LLButton::setImageDisabled(LLPointer image) { mImageDisabled = image; mDisabledImageColor = mImageColor; - mDisabledImageColor.mV[VALPHA] *= 0.5f; + mFadeWhenDisabled = TRUE; } void LLButton::setImageDisabledSelected(LLPointer image) { mImageDisabledSelected = image; mDisabledImageColor = mImageColor; - mDisabledImageColor.mV[VALPHA] *= 0.5f; -} - -void LLButton::setDisabledImages( const std::string &image_name, const std::string &selected_name, const LLColor4& c ) -{ - setImageDisabled(image_name); - setImageDisabledSelected(selected_name); - mDisabledImageColor = c; + mFadeWhenDisabled = TRUE; } void LLButton::setImageHoverSelected(LLPointer image) @@ -875,22 +1048,14 @@ void LLButton::setImageHoverSelected(LLPointer image) mImageHoverSelected = image; } -void LLButton::setDisabledImages( const std::string &image_name, const std::string &selected_name) -{ - LLColor4 clr = mImageColor; - clr.mV[VALPHA] *= .5f; - setDisabledImages( image_name, selected_name, clr ); -} - void LLButton::setImageHoverUnselected(LLPointer image) { mImageHoverUnselected = image; } -void LLButton::setHoverImages( const std::string& image_name, const std::string& selected_name ) +void LLButton::setImageFlash(LLPointer image) { - setImageHoverUnselected(image_name); - setImageHoverSelected(selected_name); + mImageFlash = image; } void LLButton::setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment, const LLColor4& color) @@ -907,11 +1072,23 @@ void LLButton::setImageOverlay(const std::string& image_name, LLFontGL::HAlign a } } +void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment, const LLColor4& color) +{ + if (image_id.isNull()) + { + mImageOverlay = NULL; + } + else + { + mImageOverlay = LLUI::getUIImageByID(image_id); + mImageOverlayAlignment = alignment; + mImageOverlayColor = color; + } +} void LLButton::onMouseCaptureLost() { - mMouseDownTimer.stop(); - mMouseDownTimer.reset(); + resetMouseDownTimer(); } //------------------------------------------------------------------------- @@ -932,55 +1109,23 @@ S32 round_up(S32 grid, S32 value) } } -void LLButton::setImageUnselected(const std::string &image_name) -{ - setImageUnselected(LLUI::getUIImage(image_name)); - mImageUnselectedName = image_name; -} - -void LLButton::setImageSelected(const std::string &image_name) -{ - setImageSelected(LLUI::getUIImage(image_name)); - mImageSelectedName = image_name; -} - -void LLButton::setImageHoverSelected(const std::string &image_name) -{ - setImageHoverSelected(LLUI::getUIImage(image_name)); - mImageHoverSelectedName = image_name; -} - -void LLButton::setImageHoverUnselected(const std::string &image_name) -{ - setImageHoverUnselected(LLUI::getUIImage(image_name)); - mImageHoverUnselectedName = image_name; -} - -void LLButton::setImageDisabled(const std::string &image_name) -{ - setImageDisabled(LLUI::getUIImage(image_name)); - mImageDisabledName = image_name; -} - -void LLButton::setImageDisabledSelected(const std::string &image_name) -{ - setImageDisabledSelected(LLUI::getUIImage(image_name)); - mImageDisabledSelectedName = image_name; -} - void LLButton::addImageAttributeToXML(LLXMLNodePtr node, - const std::string& image_name, - const LLUUID& image_id, + const LLPointer image, const std::string& xml_tag_name) const { - if( !image_name.empty() ) - { + if(!image) + return; + + const std::string image_name = image->getName(); + + if(image_name.empty()) + return; + + LLUUID id; + if(!id.set(image_name, false)) node->createChild(xml_tag_name.c_str(), TRUE)->setStringValue(image_name); - } - else if( image_id != LLUUID::null ) - { - node->createChild((xml_tag_name + "_id").c_str(), TRUE)->setUUIDValue(image_id); - } + else + node->createChild((xml_tag_name + "_id").c_str(), TRUE)->setUUIDValue(id); } // virtual @@ -995,12 +1140,12 @@ LLXMLNodePtr LLButton::getXML(bool save_children) const node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont)); node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign)); - addImageAttributeToXML(node,mImageUnselectedName,mImageUnselectedID,std::string("image_unselected")); - addImageAttributeToXML(node,mImageSelectedName,mImageSelectedID,std::string("image_selected")); - addImageAttributeToXML(node,mImageHoverSelectedName,mImageHoverSelectedID,std::string("image_hover_selected")); - addImageAttributeToXML(node,mImageHoverUnselectedName,mImageHoverUnselectedID,std::string("image_hover_unselected")); - addImageAttributeToXML(node,mImageDisabledName,mImageDisabledID,std::string("image_disabled")); - addImageAttributeToXML(node,mImageDisabledSelectedName,mImageDisabledSelectedID,std::string("image_disabled_selected")); + addImageAttributeToXML(node,mImageUnselected,std::string("image_unselected")); + addImageAttributeToXML(node,mImageSelected,std::string("image_selected")); + addImageAttributeToXML(node,mImageHoverSelected,std::string("image_hover_selected")); + addImageAttributeToXML(node,mImageHoverUnselected,std::string("image_hover_unselected")); + addImageAttributeToXML(node,mImageDisabled,std::string("image_disabled")); + addImageAttributeToXML(node,mImageDisabledSelected,std::string("image_disabled_selected")); node->createChild("scale_image", TRUE)->setBoolValue(mScaleImage); @@ -1082,13 +1227,13 @@ LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa node->getAttributeBOOL("toggle", is_toggle); button->setIsToggle(is_toggle); - if(image_hover_selected != LLStringUtil::null) button->setImageHoverSelected(image_hover_selected); + if(image_hover_selected != LLStringUtil::null) button->setImageHoverSelected(LLUI::getUIImage(image_hover_selected)); - if(image_hover_unselected != LLStringUtil::null) button->setImageHoverUnselected(image_hover_unselected); + if(image_hover_unselected != LLStringUtil::null) button->setImageHoverUnselected(LLUI::getUIImage(image_hover_unselected)); - if(image_disabled_selected != LLStringUtil::null) button->setImageDisabledSelected(image_disabled_selected ); + if(image_disabled_selected != LLStringUtil::null) button->setImageDisabledSelected(LLUI::getUIImage(image_disabled_selected)); - if(image_disabled != LLStringUtil::null) button->setImageDisabled(image_disabled); + if(image_disabled != LLStringUtil::null) button->setImageDisabled(LLUI::getUIImage(image_disabled)); if(image_overlay != LLStringUtil::null) button->setImageOverlay(image_overlay, image_overlay_alignment); @@ -1126,6 +1271,18 @@ LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa return button; } +void LLButton::resetMouseDownTimer() +{ + mMouseDownTimer.stop(); + mMouseDownTimer.reset(); +} + +BOOL LLButton::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + // just treat a double click as a second click + return handleMouseDown(x, y, mask); +} + void LLButton::setHelpURLCallback(const std::string &help_url) { mHelpURL = help_url; diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index d9fde0ea8..039ee034b 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -41,6 +41,8 @@ #include "llfontgl.h" #include "lluiimage.h" #include "lluistring.h" +#include "llinitparam.h" +#include "lluicolor.h" // // Constants @@ -85,21 +87,26 @@ public: const LLFontGL* mGLFont = NULL, const std::string& unselected_label = LLStringUtil::null, const std::string& selected_label = LLStringUtil::null ); +public: - virtual ~LLButton(); - void init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const std::string& control_name); + ~LLButton(); + // For backward compatability only + typedef boost::function button_callback_t; - - void addImageAttributeToXML(LLXMLNodePtr node, const std::string& imageName, - const LLUUID& imageID,const std::string& xmlTagName) const; + void addImageAttributeToXML(LLXMLNodePtr node, const LLPointer, const std::string& xmlTagName) const; + void init(void (*click_callback)(void*), void *callback_data, const std::string& control_name); virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); + static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); + virtual void setAlpha( F32 alpha ) { mAlpha = alpha; } virtual BOOL handleUnicodeCharHere(llwchar uni_char); virtual BOOL handleKeyHere(KEY key, MASK mask); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); + virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); virtual void draw(); virtual void onMouseCaptureLost(); @@ -109,29 +116,48 @@ public: void setUnselectedLabelColor( const LLColor4& c ) { mUnselectedLabelColor = c; } void setSelectedLabelColor( const LLColor4& c ) { mSelectedLabelColor = c; } - void setClickedCallback( void (*cb)(void *data), void* data = NULL ); // mouse down and up within button - void setMouseDownCallback( void (*cb)(void *data) ) { mMouseDownCallback = cb; } // mouse down within button - void setMouseUpCallback( void (*cb)(void *data) ) { mMouseUpCallback = cb; } // mouse up, EVEN IF NOT IN BUTTON - void setHeldDownCallback( void (*cb)(void *data) ) { mHeldDownCallback = cb; } // Mouse button held down and in button + + /*boost::signals2::connection setClickedCallback(const CommitCallbackParam& cb); + boost::signals2::connection setMouseDownCallback(const CommitCallbackParam& cb); + boost::signals2::connection setMouseUpCallback(const CommitCallbackParam& cb); + boost::signals2::connection setHeldDownCallback(const CommitCallbackParam& cb);*/ + + boost::signals2::connection setClickedCallback( const commit_signal_t::slot_type& cb ); // mouse down and up within button + boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); // mouse up, EVEN IF NOT IN BUTTON + // Passes a 'count' parameter in the commit param payload, i.e. param["count"]) + boost::signals2::connection setHeldDownCallback( const commit_signal_t::slot_type& cb ); // Mouse button held down and in button + + + // *TODO: Deprecate (for backwards compatability only) + boost::signals2::connection setClickedCallback( button_callback_t cb, void* data ); + boost::signals2::connection setMouseDownCallback( button_callback_t cb, void* data ); + boost::signals2::connection setMouseUpCallback( button_callback_t cb, void* data ); + boost::signals2::connection setHeldDownCallback( button_callback_t cb, void* data ); + void setHeldDownDelay( F32 seconds, S32 frames = 0) { mHeldDownDelay = seconds; mHeldDownFrameDelay = frames; } F32 getHeldDownTime() const { return mMouseDownTimer.getElapsedTimeF32(); } - BOOL getIsToggle() const { return mIsToggle; } - void setIsToggle(BOOL is_toggle) { mIsToggle = is_toggle; } BOOL toggleState(); - BOOL getToggleState() const { return mToggleState; } + BOOL getToggleState() const; void setToggleState(BOOL b); + void setHighlight(bool b); void setFlashing( BOOL b ); BOOL getFlashing() const { return mFlashing; } void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } LLFontGL::HAlign getHAlign() const { return mHAlign; } void setLeftHPad( S32 pad ) { mLeftHPad = pad; } - S32 getLeftHPad() const { return mLeftHPad; } + S32 getLeftHPad() const { return mLeftHPad; } void setRightHPad( S32 pad ) { mRightHPad = pad; } - S32 getRightHPad() const { return mRightHPad; } + S32 getRightHPad() const { return mRightHPad; } + + void setImageOverlayTopPad( S32 pad ) { mImageOverlayTopPad = pad; } + S32 getImageOverlayTopPad() const { return mImageOverlayTopPad; } + void setImageOverlayBottomPad( S32 pad ) { mImageOverlayBottomPad = pad; } + S32 getImageOverlayBottomPad() const { return mImageOverlayBottomPad; } const std::string getLabelUnselected() const { return wstring_to_utf8str(mUnselectedLabel); } const std::string getLabelSelected() const { return wstring_to_utf8str(mSelectedLabel); } @@ -139,35 +165,31 @@ public: void setImageColor(const std::string& color_control); void setImageColor(const LLColor4& c); /*virtual*/ void setColor(const LLColor4& c); - /*virtual*/ void setAlpha(F32 alpha); void setImages(const std::string &image_name, const std::string &selected_name); - void setDisabledImages(const std::string &image_name, const std::string &selected_name); - void setDisabledImages(const std::string &image_name, const std::string &selected_name, const LLColor4& c); - - void setHoverImages(const std::string &image_name, const std::string &selected_name); void setDisabledImageColor(const LLColor4& c) { mDisabledImageColor = c; } void setDisabledSelectedLabelColor( const LLColor4& c ) { mDisabledSelectedLabelColor = c; } void setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white); + void setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white); LLPointer getImageOverlay() { return mImageOverlay; } + LLFontGL::HAlign getImageOverlayHAlign() const { return mImageOverlayAlignment; } - - virtual void setValue(const LLSD& value ); - virtual LLSD getValue() const; - + void autoResize(); // resize with label of current btn state + void resize(LLUIString label); // resize with label input void setLabel( const LLStringExplicit& label); virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); void setLabelUnselected(const LLStringExplicit& label); void setLabelSelected(const LLStringExplicit& label); - void setDisabledLabel(const LLStringExplicit& disabled_label); - void setDisabledSelectedLabel(const LLStringExplicit& disabled_label); void setDisabledLabelColor( const LLColor4& c ) { mDisabledLabelColor = c; } void setFont(const LLFontGL *font) { mGLFont = ( font ? font : LLFontGL::getFontSansSerif()); } + const LLFontGL* getFont() const { return mGLFont; } + const LLUIString& getCurrentLabel() const; + void setScaleImage(BOOL scale) { mScaleImage = scale; } BOOL getScaleImage() const { return mScaleImage; } @@ -175,132 +197,130 @@ public: void setBorderEnabled(BOOL b) { mBorderEnabled = b; } - static void onHeldDown(void *userdata); // to be called by gIdleCallbacks - void setHoverGlowStrength(F32 strength) { mHoverGlowStrength = strength; } - void setImageUnselected(const std::string &image_name); - const std::string& getImageUnselectedName() const { return mImageUnselectedName; } - void setImageSelected(const std::string &image_name); - const std::string& getImageSelectedName() const { return mImageSelectedName; } - void setImageHoverSelected(const std::string &image_name); - void setImageHoverUnselected(const std::string &image_name); - void setImageDisabled(const std::string &image_name); - void setImageDisabledSelected(const std::string &image_name); - void setImageUnselected(LLPointer image); void setImageSelected(LLPointer image); void setImageHoverSelected(LLPointer image); void setImageHoverUnselected(LLPointer image); void setImageDisabled(LLPointer image); void setImageDisabledSelected(LLPointer image); - + void setImageFlash(LLPointer image); + void setImagePressed(LLPointer image); + void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; } BOOL getCommitOnReturn() const { return mCommitOnReturn; } + static void onHeldDown(void *userdata); // to be called by gIdleCallbacks void setHelpURLCallback(const std::string &help_url); const std::string& getHelpURL() const { return mHelpURL; } + void setForcePressedState(bool b) { mForcePressedState = b; } + + void setAutoResize(bool auto_resize) { mAutoResize = auto_resize; } + + bool getIsToggle() const { return mIsToggle; } + bool setIsToggle(bool toggle) { return mIsToggle = toggle; } + protected: - - virtual void drawBorder(const LLColor4& color, S32 size); - - void setImageUnselectedID(const LLUUID &image_id); - const LLUUID& getImageUnselectedID() const { return mImageUnselectedID; } - void setImageSelectedID(const LLUUID &image_id); - const LLUUID& getImageSelectedID() const { return mImageSelectedID; } - void setImageHoverSelectedID(const LLUUID &image_id); - void setImageHoverUnselectedID(const LLUUID &image_id); - void setImageDisabledID(const LLUUID &image_id); - void setImageDisabledSelectedID(const LLUUID &image_id); const LLPointer& getImageUnselected() const { return mImageUnselected; } const LLPointer& getImageSelected() const { return mImageSelected; } - + void getOverlayImageSize(S32& overlay_width, S32& overlay_height); + LLFrameTimer mMouseDownTimer; + bool mNeedsHighlight; + S32 mButtonFlashCount; + F32 mButtonFlashRate; -private: - - void (*mClickedCallback)(void* data ); - void (*mMouseDownCallback)(void *data); - void (*mMouseUpCallback)(void *data); - void (*mHeldDownCallback)(void *data); + void drawBorder(LLUIImage* imagep, const LLColor4& color, S32 size); + void resetMouseDownTimer(); + commit_signal_t* mMouseDownSignal; + commit_signal_t* mMouseUpSignal; + commit_signal_t* mHeldDownSignal; + const LLFontGL *mGLFont; - S32 mMouseDownFrame; - F32 mHeldDownDelay; // seconds, after which held-down callbacks get called - S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called + S32 mMouseDownFrame; + S32 mMouseHeldDownCount; // Counter for parameter passed to held-down callback + F32 mHeldDownDelay; // seconds, after which held-down callbacks get called + S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called LLPointer mImageOverlay; - LLFontGL::HAlign mImageOverlayAlignment; - LLColor4 mImageOverlayColor; + LLFontGL::HAlign mImageOverlayAlignment; + LLUIColor mImageOverlayColor; + LLUIColor mImageOverlaySelectedColor; + LLUIColor mImageOverlayDisabledColor; - LLPointer mImageUnselected; - LLUIString mUnselectedLabel; - LLColor4 mUnselectedLabelColor; + LLPointer mImageUnselected; + LLUIString mUnselectedLabel; + LLUIColor mUnselectedLabelColor; - LLPointer mImageSelected; - LLUIString mSelectedLabel; - LLColor4 mSelectedLabelColor; + LLPointer mImageSelected; + LLUIString mSelectedLabel; + LLUIColor mSelectedLabelColor; - LLPointer mImageHoverSelected; + LLPointer mImageHoverSelected; - LLPointer mImageHoverUnselected; + LLPointer mImageHoverUnselected; - LLPointer mImageDisabled; - LLUIString mDisabledLabel; - LLColor4 mDisabledLabelColor; + LLPointer mImageDisabled; + LLUIColor mDisabledLabelColor; - LLPointer mImageDisabledSelected; - LLUIString mDisabledSelectedLabel; - LLColor4 mDisabledSelectedLabelColor; + LLPointer mImageDisabledSelected; + LLUIString mDisabledSelectedLabel; + LLUIColor mDisabledSelectedLabelColor; - LLUUID mImageUnselectedID; - LLUUID mImageSelectedID; - LLUUID mImageHoverSelectedID; - LLUUID mImageHoverUnselectedID; - LLUUID mImageDisabledID; - LLUUID mImageDisabledSelectedID; - std::string mImageUnselectedName; - std::string mImageSelectedName; - std::string mImageHoverSelectedName; - std::string mImageHoverUnselectedName; - std::string mImageDisabledName; - std::string mImageDisabledSelectedName; + LLPointer mImagePressed; + LLPointer mImagePressedSelected; - LLColor4 mHighlightColor; - LLColor4 mUnselectedBgColor; - LLColor4 mSelectedBgColor; - LLColor4 mFlashBgColor; + /* There are two ways an image can flash- by making changes in color according to flash_color attribute + or by changing icon from current to the one specified in image_flash. Second way is used only if + flash icon name is set in attributes(by default it isn't). First way is used otherwise. */ + LLPointer mImageFlash; - LLColor4 mImageColor; - LLColor4 mDisabledImageColor; + LLUIColor mFlashBgColor; - BOOL mIsToggle; - BOOL mToggleState; - BOOL mScaleImage; + LLUIColor mImageColor; + LLUIColor mDisabledImageColor; - BOOL mDropShadowedText; + bool mIsToggle; + bool mScaleImage; - BOOL mBorderEnabled; + bool mDropShadowedText; + bool mAutoResize; + bool mBorderEnabled; + bool mFlashing; - BOOL mFlashing; + LLFontGL::HAlign mHAlign; + S32 mLeftHPad; + S32 mRightHPad; + S32 mBottomVPad; // under text label - LLFontGL::HAlign mHAlign; - S32 mLeftHPad; - S32 mRightHPad; + S32 mImageOverlayTopPad; + S32 mImageOverlayBottomPad; - F32 mHoverGlowStrength; - F32 mCurGlowStrength; + /* + * Space between image_overlay and label + */ + S32 mImgOverlayLabelSpace; - BOOL mNeedsHighlight; - BOOL mCommitOnReturn; + F32 mHoverGlowStrength; + F32 mCurGlowStrength; - std::string mHelpURL; + bool mCommitOnReturn; + bool mFadeWhenDisabled; - LLPointer mImagep; + bool mForcePressedState; + bool mDisplayPressedState; - LLFrameTimer mFlashingTimer; + std::string mHelpURL; + + LLFrameTimer mFlashingTimer; + + bool mHandleRightMouse; + + F32 mAlpha; }; #endif // LL_LLBUTTON_H diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index c1daee798..c7ed9ba34 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -113,37 +113,27 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const std::string& name, const LLRect& rect, LLCHECKBOXCTRL_VPAD, LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING + text_width + LLCHECKBOXCTRL_HPAD, llmax( text_height, LLCHECKBOXCTRL_BTN_SIZE ) + LLCHECKBOXCTRL_VPAD); - std::string active_true_id, active_false_id; - std::string inactive_true_id, inactive_false_id; - if (mRadioStyle) - { - active_true_id = "UIImgRadioActiveSelectedUUID"; - active_false_id = "UIImgRadioActiveUUID"; - inactive_true_id = "UIImgRadioInactiveSelectedUUID"; - inactive_false_id = "UIImgRadioInactiveUUID"; - mButton = new LLButton(std::string("Radio control button"), btn_rect, - active_false_id, active_true_id, control_which, - &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::getFontSansSerif() ); - mButton->setDisabledImages( inactive_false_id, inactive_true_id ); - mButton->setHoverGlowStrength(0.35f); - } - else - { - active_false_id = "UIImgCheckboxActiveUUID"; - active_true_id = "UIImgCheckboxActiveSelectedUUID"; - inactive_true_id = "UIImgCheckboxInactiveSelectedUUID"; - inactive_false_id = "UIImgCheckboxInactiveUUID"; - mButton = new LLButton(std::string("Checkbox control button"), btn_rect, - active_false_id, active_true_id, control_which, - &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::getFontSansSerif() ); - mButton->setDisabledImages( inactive_false_id, inactive_true_id ); - mButton->setHoverGlowStrength(0.35f); - } + + std::string active_true_id = mRadioStyle ? "UIImgRadioActiveSelectedUUID" : "UIImgCheckboxActiveSelectedUUID"; + std::string active_false_id = mRadioStyle ? "UIImgRadioActiveUUID" : "UIImgCheckboxActiveUUID"; + std::string inactive_true_id = mRadioStyle ? "UIImgRadioInactiveSelectedUUID" : "UIImgCheckboxInactiveSelectedUUID"; + std::string inactive_false_id = mRadioStyle ? "UIImgRadioInactiveUUID" : "UIImgCheckboxInactiveUUID"; + std::string button_name = mRadioStyle ? "Radio control button" : "Checkbox control button"; + + mButton = new LLButton( button_name, btn_rect, + active_false_id, active_true_id, control_which, + &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::getFontSansSerif() ); + + mButton->setImageDisabledSelected(LLUI::getUIImage(inactive_true_id)); + mButton->setImageDisabled(LLUI::getUIImage(inactive_false_id)); + mButton->setHoverGlowStrength(0.35f); + mButton->setIsToggle(TRUE); mButton->setToggleState( initial_value ); mButton->setFollowsLeft(); mButton->setFollowsBottom(); mButton->setCommitOnReturn(FALSE); + mButton->setScaleImage(FALSE); addChild(mButton); } @@ -156,22 +146,8 @@ LLCheckBoxCtrl::~LLCheckBoxCtrl() // static void LLCheckBoxCtrl::onButtonPress( void *userdata ) { - LLCheckBoxCtrl* self = (LLCheckBoxCtrl*) userdata; - - if (self->mRadioStyle) - { - self->setValue(TRUE); - } - - self->setControlValue(self->getValue()); - // HACK: because buttons don't normally commit + LLCheckBoxCtrl* self = (LLCheckBoxCtrl*)userdata; self->onCommit(); - - if (self->mKeyboardFocusOnClick) - { - self->setFocus( TRUE ); - self->onFocusReceived(); - } } void LLCheckBoxCtrl::onCommit() @@ -179,6 +155,7 @@ void LLCheckBoxCtrl::onCommit() if( getEnabled() ) { setTentative(FALSE); + setControlValue(getValue()); LLUICtrl::onCommit(); } } @@ -186,7 +163,15 @@ void LLCheckBoxCtrl::onCommit() void LLCheckBoxCtrl::setEnabled(BOOL b) { LLView::setEnabled(b); - mButton->setEnabled(b); + + if (b) + { + mLabel->setColor( mTextEnabledColor.get() ); + } + else + { + mLabel->setColor( mTextDisabledColor.get() ); + } } void LLCheckBoxCtrl::clear() @@ -219,21 +204,6 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) LLUICtrl::reshape(width, height, called_from_parent); } -void LLCheckBoxCtrl::draw() -{ - if (getEnabled()) - { - mLabel->setColor( mTextEnabledColor ); - } - else - { - mLabel->setColor( mTextDisabledColor ); - } - - // Draw children - LLUICtrl::draw(); -} - //virtual void LLCheckBoxCtrl::setValue(const LLSD& value ) { @@ -246,6 +216,18 @@ LLSD LLCheckBoxCtrl::getValue() const return mButton->getValue(); } +//virtual +void LLCheckBoxCtrl::setTentative(BOOL b) +{ + mButton->setTentative(b); +} + +//virtual +BOOL LLCheckBoxCtrl::getTentative() const +{ + return mButton->getTentative(); +} + void LLCheckBoxCtrl::setLabel( const LLStringExplicit& label ) { mLabel->setText( label ); @@ -282,7 +264,7 @@ BOOL LLCheckBoxCtrl::isDirty() const { if ( mButton ) { - return (mSetValue != mButton->getToggleState()); + return mButton->isDirty(); } return FALSE; // Shouldn't get here } @@ -293,11 +275,12 @@ void LLCheckBoxCtrl::resetDirty() { if ( mButton ) { - mSetValue = mButton->getToggleState(); + mButton->resetDirty(); } } + // virtual LLXMLNodePtr LLCheckBoxCtrl::getXML(bool save_children) const { diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index ff867f519..b9f8bec6f 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -82,7 +82,6 @@ public: virtual void setEnabled( BOOL b ); - virtual void draw(); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); // LLUICtrl interface @@ -91,8 +90,8 @@ public: BOOL get() { return (BOOL)getValue().asBoolean(); } void set(BOOL value) { setValue(value); } - virtual void setTentative(BOOL b) { mButton->setTentative(b); } - virtual BOOL getTentative() const { return mButton->getTentative(); } + virtual void setTentative(BOOL b); + virtual BOOL getTentative() const; virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); @@ -108,6 +107,9 @@ public: void setLabel( const LLStringExplicit& label ); std::string getLabel() const; + void setFont( const LLFontGL* font ) { mFont = font; } + const LLFontGL* getFont() { return mFont; } + virtual void setControlName(const std::string& control_name, LLView* context); virtual std::string getControlName() const; @@ -121,8 +123,9 @@ protected: LLButton* mButton; LLTextBox* mLabel; const LLFontGL* mFont; - LLColor4 mTextEnabledColor; - LLColor4 mTextDisabledColor; + + LLUIColor mTextEnabledColor; + LLUIColor mTextDisabledColor; BOOL mRadioStyle; BOOL mInitialValue; // Value set in constructor BOOL mSetValue; // Value set programmatically diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 507414958..b1b8f42e4 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -85,13 +85,13 @@ LLComboBox::LLComboBox( const std::string& name, const LLRect &rect, const std:: LLRect(), LLStringUtil::null, NULL, this); - mButton->setImageUnselected(std::string("square_btn_32x128.tga")); - mButton->setImageSelected(std::string("square_btn_selected_32x128.tga")); - mButton->setImageDisabled(std::string("square_btn_32x128.tga")); - mButton->setImageDisabledSelected(std::string("square_btn_selected_32x128.tga")); + mButton->setImageUnselected(LLUI::getUIImage("square_btn_32x128.tga")); + mButton->setImageSelected(LLUI::getUIImage("square_btn_selected_32x128.tga")); + mButton->setImageDisabled(LLUI::getUIImage("square_btn_32x128.tga")); + mButton->setImageDisabledSelected(LLUI::getUIImage("square_btn_selected_32x128.tga")); mButton->setScaleImage(TRUE); - mButton->setMouseDownCallback(onButtonDown); + mButton->setMouseDownCallback(boost::bind(&LLComboBox::onButtonDown,this)); mButton->setFont(LLFontGL::getFontSansSerifSmall()); mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT); mButton->setHAlign( LLFontGL::LEFT ); @@ -110,13 +110,11 @@ LLComboBox::LLComboBox( const std::string& name, const LLRect &rect, const std:: mButton->setImageOverlay("combobox_arrow.tga", LLFontGL::RIGHT); updateLayout(); + + mTopLostSignalConnection = setTopLostCallback(boost::bind(&LLComboBox::hideList, this)); } -LLComboBox::~LLComboBox() -{ - // children automatically deleted, including mMenu, mButton -} // virtual LLXMLNodePtr LLComboBox::getXML(bool save_children) const @@ -228,6 +226,16 @@ void LLComboBox::setEnabled(BOOL enabled) mButton->setEnabled(enabled); } + +LLComboBox::~LLComboBox() +{ + // children automatically deleted, including mMenu, mButton + + // explicitly disconect this signal, since base class destructor might fire top lost + mTopLostSignalConnection.disconnect(); +} + + void LLComboBox::clear() { if (mTextEntry) @@ -236,8 +244,6 @@ void LLComboBox::clear() } mButton->setLabelSelected(LLStringUtil::null); mButton->setLabelUnselected(LLStringUtil::null); - mButton->setDisabledLabel(LLStringUtil::null); - mButton->setDisabledSelectedLabel(LLStringUtil::null); mList->deselectAllItems(); } @@ -437,8 +443,6 @@ void LLComboBox::setLabel(const LLStringExplicit& name) { mButton->setLabelUnselected(name); mButton->setLabelSelected(name); - mButton->setDisabledLabel(name); - mButton->setDisabledSelectedLabel(name); } } @@ -481,12 +485,6 @@ void LLComboBox::onFocusLost() LLUICtrl::onFocusLost(); } -void LLComboBox::onLostTop() -{ - hideList(); -} - - void LLComboBox::setButtonVisible(BOOL visible) { mButton->setVisible(visible); @@ -749,10 +747,10 @@ void LLComboBox::onButtonDown(void *userdata) self->setFocus( TRUE ); // pass mouse capture on to list if button is depressed - if (self->mButton->hasMouseCapture()) + /*if (self->mButton->hasMouseCapture()) { gFocusMgr.setMouseCapture(self->mList); - } + }*/ } else { @@ -1216,7 +1214,7 @@ LLFlyoutButton::LLFlyoutButton( LLRect(), LLStringUtil::null, NULL, this); mActionButton->setScaleImage(TRUE); - mActionButton->setClickedCallback(onActionButtonClick); + mActionButton->setClickedCallback(boost::bind(&LLFlyoutButton::onActionButtonClick, this)); mActionButton->setFollowsAll(); mActionButton->setHAlign( LLFontGL::HCENTER ); mActionButton->setLabel(label); diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 3ed035187..a1be4cab3 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -80,7 +80,6 @@ public: virtual void draw(); virtual void onFocusLost(); - virtual void onLostTop(); virtual void setEnabled(BOOL enabled); @@ -212,6 +211,7 @@ private: bool mSuppressTentative; void (*mPrearrangeCallback)(LLUICtrl*,void*); void (*mTextEntryCallback)(LLLineEditor*, void*); + boost::signals2::connection mTopLostSignalConnection; }; class LLFlyoutButton : public LLComboBox diff --git a/indra/llui/lldelayeduidelete.h b/indra/llui/lldelayeduidelete.h index 043e6972e..131e43424 100644 --- a/indra/llui/lldelayeduidelete.h +++ b/indra/llui/lldelayeduidelete.h @@ -7,6 +7,7 @@ class LLDeleteJob { public: virtual BOOL work(U32& completed); + virtual ~LLDeleteJob() {} }; class LLViewDeleteJob : public LLDeleteJob { diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 08924ac11..114cabc0c 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -430,6 +430,27 @@ void LLFloater::initFloater(const std::string& title, } } +void LLFloater::enableResizeCtrls(bool enable, bool width, bool height) +{ + mResizeBar[LLResizeBar::LEFT]->setVisible(enable && width); + mResizeBar[LLResizeBar::LEFT]->setEnabled(enable && width); + + mResizeBar[LLResizeBar::TOP]->setVisible(enable && height); + mResizeBar[LLResizeBar::TOP]->setEnabled(enable && height); + + mResizeBar[LLResizeBar::RIGHT]->setVisible(enable && width); + mResizeBar[LLResizeBar::RIGHT]->setEnabled(enable && width); + + mResizeBar[LLResizeBar::BOTTOM]->setVisible(enable && height); + mResizeBar[LLResizeBar::BOTTOM]->setEnabled(enable && height); + + for (S32 i = 0; i < 4; ++i) + { + mResizeHandle[i]->setVisible(enable && width && height); + mResizeHandle[i]->setEnabled(enable && width && height); + } +} + // virtual LLFloater::~LLFloater() { @@ -707,6 +728,8 @@ const std::string& LLFloater::getCurrentTitle() const void LLFloater::setTitle( const std::string& title ) { + if(mTitle == title) + return; mTitle = title; applyTitle(); } @@ -1542,10 +1565,12 @@ void LLFloater::setCanResize(BOOL can_resize) { for (S32 i = 0; i < 4; i++) { - removeChild(mResizeBar[i], TRUE); + removeChild(mResizeBar[i]); + delete mResizeBar[i]; mResizeBar[i] = NULL; - removeChild(mResizeHandle[i], TRUE); + removeChild(mResizeHandle[i]); + delete mResizeHandle[i]; mResizeHandle[i] = NULL; } } @@ -1611,6 +1636,7 @@ void LLFloater::setCanResize(BOOL can_resize) mMinHeight, LLResizeHandle::LEFT_TOP ); addChild(mResizeHandle[3]); + enableResizeCtrls(can_resize); } mResizable = can_resize; } @@ -1714,8 +1740,8 @@ void LLFloater::buildButtons() buttonp->setFollowsRight(); buttonp->setToolTip( sButtonToolTips[i] ); buttonp->setImageColor(LLUI::sColorsGroup->getColor("FloaterButtonImageColor")); - buttonp->setHoverImages(sButtonPressedImageNames[i], - sButtonPressedImageNames[i]); + buttonp->setImageHoverSelected(LLUI::getUIImage(sButtonPressedImageNames[i])); + buttonp->setImageHoverUnselected(LLUI::getUIImage(sButtonPressedImageNames[i])); buttonp->setScaleImage(TRUE); buttonp->setSaveToXML(false); addChild(buttonp); @@ -2459,8 +2485,12 @@ void LLFloaterView::pushVisibleAll(BOOL visible, const skip_list_t& skip_list) void LLFloaterView::popVisibleAll(const skip_list_t& skip_list) { - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) + // make a copy of the list since some floaters change their + // order in the childList when changing visibility. + child_list_t child_list_copy = *getChildList(); + + for (child_list_const_iter_t child_iter = child_list_copy.begin(); + child_iter != child_list_copy.end(); ++child_iter) { LLView *view = *child_iter; if (skip_list.find(view) == skip_list.end()) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 939071b0f..b61a567bb 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -250,6 +250,7 @@ public: static BOOL getEditModeEnabled() { return sEditModeEnabled; } static LLMultiFloater* getFloaterHost() {return sHostp; } + void enableResizeCtrls(bool enable, bool width = true, bool height = true); protected: virtual void bringToFront(S32 x, S32 y); diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp index 96b01b98f..66834a6a1 100644 --- a/indra/llui/llfocusmgr.cpp +++ b/indra/llui/llfocusmgr.cpp @@ -2,31 +2,25 @@ * @file llfocusmgr.cpp * @brief LLFocusMgr base class * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,13 +32,11 @@ const F32 FOCUS_FADE_TIME = 0.3f; -// NOTE: the LLFocusableElement implementation has been here from lluictrl.cpp. - LLFocusableElement::LLFocusableElement() : mFocusLostCallback(NULL), mFocusReceivedCallback(NULL), mFocusChangedCallback(NULL), - mFocusCallbackUserData(NULL) + mTopLostCallback(NULL) { } @@ -63,31 +55,27 @@ BOOL LLFocusableElement::handleUnicodeChar(llwchar uni_char, BOOL called_from_pa // virtual LLFocusableElement::~LLFocusableElement() { + delete mFocusLostCallback; + delete mFocusReceivedCallback; + delete mFocusChangedCallback; + delete mTopLostCallback; } void LLFocusableElement::onFocusReceived() { - if( mFocusReceivedCallback ) - { - mFocusReceivedCallback( this, mFocusCallbackUserData ); - } - if( mFocusChangedCallback ) - { - mFocusChangedCallback( this, mFocusCallbackUserData ); - } + if (mFocusReceivedCallback) (*mFocusReceivedCallback)(this); + if (mFocusChangedCallback) (*mFocusChangedCallback)(this); } void LLFocusableElement::onFocusLost() { - if( mFocusLostCallback ) - { - mFocusLostCallback( this, mFocusCallbackUserData ); - } + if (mFocusLostCallback) (*mFocusLostCallback)(this); + if (mFocusChangedCallback) (*mFocusChangedCallback)(this); +} - if( mFocusChangedCallback ) - { - mFocusChangedCallback( this, mFocusCallbackUserData ); - } +void LLFocusableElement::onTopLost() +{ + if (mTopLostCallback) (*mTopLostCallback)(this); } BOOL LLFocusableElement::hasFocus() const @@ -99,28 +87,63 @@ void LLFocusableElement::setFocus(BOOL b) { } +boost::signals2::connection LLFocusableElement::setFocusLostCallback( const focus_signal_t::slot_type& cb) +{ + if (!mFocusLostCallback) mFocusLostCallback = new focus_signal_t(); + return mFocusLostCallback->connect(cb); +} + +boost::signals2::connection LLFocusableElement::setFocusReceivedCallback(const focus_signal_t::slot_type& cb) +{ + if (!mFocusReceivedCallback) mFocusReceivedCallback = new focus_signal_t(); + return mFocusReceivedCallback->connect(cb); +} + +boost::signals2::connection LLFocusableElement::setFocusChangedCallback(const focus_signal_t::slot_type& cb) +{ + if (!mFocusChangedCallback) mFocusChangedCallback = new focus_signal_t(); + return mFocusChangedCallback->connect(cb); +} + +boost::signals2::connection LLFocusableElement::setTopLostCallback(const focus_signal_t::slot_type& cb) +{ + if (!mTopLostCallback) mTopLostCallback = new focus_signal_t(); + return mTopLostCallback->connect(cb); +} + + + +typedef std::list > view_handle_list_t; +typedef std::map, LLHandle > focus_history_map_t; +struct LLFocusMgr::Impl +{ + // caching list of keyboard focus ancestors for calling onFocusReceived and onFocusLost + view_handle_list_t mCachedKeyboardFocusList; + + focus_history_map_t mFocusHistory; +}; LLFocusMgr gFocusMgr; LLFocusMgr::LLFocusMgr() - : - mLockedView( NULL ), +: mLockedView( NULL ), mMouseCaptor( NULL ), mKeyboardFocus( NULL ), mLastKeyboardFocus( NULL ), mDefaultKeyboardFocus( NULL ), mKeystrokesOnly(FALSE), mTopCtrl( NULL ), - mFocusWeight(0.f), - mAppHasFocus(TRUE) // Macs don't seem to notify us that we've gotten focus, so default to true - #ifdef _DEBUG - , mMouseCaptorName("none") - , mKeyboardFocusName("none") - , mTopCtrlName("none") - #endif + mAppHasFocus(TRUE), // Macs don't seem to notify us that we've gotten focus, so default to true + mImpl(new LLFocusMgr::Impl) { } +LLFocusMgr::~LLFocusMgr() +{ + mImpl->mFocusHistory.clear(); + delete mImpl; + mImpl = NULL; +} void LLFocusMgr::releaseFocusIfNeeded( const LLView* view ) { @@ -151,6 +174,12 @@ void LLFocusMgr::releaseFocusIfNeeded( const LLView* view ) void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL keystrokes_only) { + // notes if keyboard focus is changed again (by onFocusLost/onFocusReceived) + // making the rest of our processing unnecessary since it will already be + // handled by the recursive call + static bool focus_dirty; + focus_dirty = false; + if (mLockedView && (new_focus == NULL || (new_focus != mLockedView @@ -162,8 +191,6 @@ void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL return; } - //llinfos << "Keyboard focus handled by " << (new_focus ? new_focus->getName() : "nothing") << llendl; - mKeystrokesOnly = keystrokes_only; if( new_focus != mKeyboardFocus ) @@ -171,23 +198,58 @@ void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL mLastKeyboardFocus = mKeyboardFocus; mKeyboardFocus = new_focus; - if( mLastKeyboardFocus ) + // list of the focus and it's ancestors + view_handle_list_t old_focus_list = mImpl->mCachedKeyboardFocusList; + view_handle_list_t new_focus_list; + + // walk up the tree to root and add all views to the new_focus_list + for (LLView* ctrl = dynamic_cast(mKeyboardFocus); ctrl; ctrl = ctrl->getParent()) { - mLastKeyboardFocus->onFocusLost(); + new_focus_list.push_back(ctrl->getHandle()); } - // clear out any existing flash - if (new_focus) + // remove all common ancestors since their focus is unchanged + while (!new_focus_list.empty() && + !old_focus_list.empty() && + new_focus_list.back() == old_focus_list.back()) { - mFocusWeight = 0.f; - new_focus->onFocusReceived(); + new_focus_list.pop_back(); + old_focus_list.pop_back(); } - mFocusTimer.reset(); - #ifdef _DEBUG - LLUICtrl* focus_ctrl = dynamic_cast(new_focus); - mKeyboardFocusName = focus_ctrl ? focus_ctrl->getName() : std::string("none"); - #endif + // walk up the old focus branch calling onFocusLost + // we bubble up the tree to release focus, and back down to add + for (view_handle_list_t::iterator old_focus_iter = old_focus_list.begin(); + old_focus_iter != old_focus_list.end() && !focus_dirty; + old_focus_iter++) + { + LLView* old_focus_view = old_focus_iter->get(); + if (old_focus_view) + { + mImpl->mCachedKeyboardFocusList.pop_front(); + old_focus_view->onFocusLost(); + } + } + + // walk down the new focus branch calling onFocusReceived + for (view_handle_list_t::reverse_iterator new_focus_riter = new_focus_list.rbegin(); + new_focus_riter != new_focus_list.rend() && !focus_dirty; + new_focus_riter++) + { + LLView* new_focus_view = new_focus_riter->get(); + if (new_focus_view) + { + mImpl->mCachedKeyboardFocusList.push_front(new_focus_view->getHandle()); + new_focus_view->onFocusReceived(); + } + } + + // if focus was changed as part of an onFocusLost or onFocusReceived call + // stop iterating on current list since it is now invalid + if (focus_dirty) + { + return; + } // If we've got a default keyboard focus, and the caller is // releasing keyboard focus, move to the default. @@ -212,7 +274,7 @@ void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL if (focus_subtree) { LLView* focused_view = dynamic_cast(mKeyboardFocus); - mFocusHistory[focus_subtree->getHandle()] = focused_view ? focused_view->getHandle() : LLHandle(); + mImpl->mFocusHistory[focus_subtree->getHandle()] = focused_view ? focused_view->getHandle() : LLHandle(); } } @@ -220,6 +282,8 @@ void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL { lockFocus(); } + + focus_dirty = true; } @@ -241,7 +305,7 @@ BOOL LLFocusMgr::childHasKeyboardFocus(const LLView* parent ) const // Returns TRUE is parent or any descedent of parent is the mouse captor. BOOL LLFocusMgr::childHasMouseCapture( const LLView* parent ) const { - if( mMouseCaptor && mMouseCaptor->isView() ) + if( mMouseCaptor && dynamic_cast(mMouseCaptor) != NULL ) { LLView* captor_view = (LLView*)mMouseCaptor; while( captor_view ) @@ -268,65 +332,42 @@ void LLFocusMgr::removeKeyboardFocusWithoutCallback( const LLFocusableElement* f if( mKeyboardFocus == focus ) { mKeyboardFocus = NULL; - #ifdef _DEBUG - mKeyboardFocusName = std::string("none"); - #endif } } void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor ) { - //if (mFocusLocked) - //{ - // return; - //} - if( new_captor != mMouseCaptor ) { LLMouseHandler* old_captor = mMouseCaptor; mMouseCaptor = new_captor; - /* - if (new_captor) + + if (LLView::sDebugMouseHandling) { - if ( new_captor->getName() == "Stickto") + if (new_captor) { llinfos << "New mouse captor: " << new_captor->getName() << llendl; } else { - llinfos << "New mouse captor: " << new_captor->getName() << llendl; + llinfos << "New mouse captor: NULL" << llendl; } } - else - { - llinfos << "New mouse captor: NULL" << llendl; - } - */ - + if( old_captor ) { old_captor->onMouseCaptureLost(); } - #ifdef _DEBUG - mMouseCaptorName = new_captor ? new_captor->getName() : std::string("none"); - #endif } } void LLFocusMgr::removeMouseCaptureWithoutCallback( const LLMouseHandler* captor ) { - //if (mFocusLocked) - //{ - // return; - //} if( mMouseCaptor == captor ) { mMouseCaptor = NULL; - #ifdef _DEBUG - mMouseCaptorName = std::string("none"); - #endif } } @@ -355,13 +396,9 @@ void LLFocusMgr::setTopCtrl( LLUICtrl* new_top ) { mTopCtrl = new_top; - #ifdef _DEBUG - mTopCtrlName = new_top ? new_top->getName() : std::string("none"); - #endif - if (old_top) { - old_top->onLostTop(); + old_top->onTopLost(); } } } @@ -371,9 +408,6 @@ void LLFocusMgr::removeTopCtrlWithoutCallback( const LLUICtrl* top_view ) if( mTopCtrl == top_view ) { mTopCtrl = NULL; - #ifdef _DEBUG - mTopCtrlName = std::string("none"); - #endif } } @@ -389,12 +423,13 @@ void LLFocusMgr::unlockFocus() F32 LLFocusMgr::getFocusFlashAmt() const { - return clamp_rescale(getFocusTime(), 0.f, FOCUS_FADE_TIME, mFocusWeight, 0.f); + return clamp_rescale(mFocusFlashTimer.getElapsedTimeF32(), 0.f, FOCUS_FADE_TIME, 1.f, 0.f); } LLColor4 LLFocusMgr::getFocusColor() const { - LLColor4 focus_color = lerp(LLUI::sColorsGroup->getColor( "FocusColor" ), LLColor4::white, getFocusFlashAmt()); + static LLCachedControl focus_color_cached(*LLUI::sColorsGroup,"FocusColor", LLColor4::white); + LLColor4 focus_color = lerp(focus_color_cached, LLColor4::white, getFocusFlashAmt()); // de-emphasize keyboard focus when app has lost focus (to avoid typing into wrong window problem) if (!mAppHasFocus) { @@ -405,8 +440,7 @@ LLColor4 LLFocusMgr::getFocusColor() const void LLFocusMgr::triggerFocusFlash() { - mFocusTimer.reset(); - mFocusWeight = 1.f; + mFocusFlashTimer.reset(); } void LLFocusMgr::setAppHasFocus(BOOL focus) @@ -428,8 +462,8 @@ LLUICtrl* LLFocusMgr::getLastFocusForGroup(LLView* subtree_root) const { if (subtree_root) { - focus_history_map_t::const_iterator found_it = mFocusHistory.find(subtree_root->getHandle()); - if (found_it != mFocusHistory.end()) + focus_history_map_t::const_iterator found_it = mImpl->mFocusHistory.find(subtree_root->getHandle()); + if (found_it != mImpl->mFocusHistory.end()) { // found last focus for this subtree return static_cast(found_it->second.get()); @@ -442,6 +476,6 @@ void LLFocusMgr::clearLastFocusForGroup(LLView* subtree_root) { if (subtree_root) { - mFocusHistory.erase(subtree_root->getHandle()); + mImpl->mFocusHistory.erase(subtree_root->getHandle()); } } diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h index ce0c75063..14c711b5e 100644 --- a/indra/llui/llfocusmgr.h +++ b/indra/llui/llfocusmgr.h @@ -2,31 +2,25 @@ * @file llfocusmgr.h * @brief LLFocusMgr base class * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,12 +32,12 @@ #include "llstring.h" #include "llframetimer.h" #include "llui.h" -#include "llhandle.h" class LLUICtrl; class LLMouseHandler; class LLView; +// NOTE: the LLFocusableElement class declaration has been moved here from lluictrl.h. class LLFocusableElement { friend class LLFocusMgr; // allow access to focus change handlers @@ -54,21 +48,25 @@ public: virtual void setFocus( BOOL b ); virtual BOOL hasFocus() const; - void setFocusLostCallback(void (*cb)(LLFocusableElement* caller, void*), void* user_data = NULL) { mFocusLostCallback = cb; mFocusCallbackUserData = user_data; } - void setFocusReceivedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL) { mFocusReceivedCallback = cb; mFocusCallbackUserData = user_data; } - void setFocusChangedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL ) { mFocusChangedCallback = cb; mFocusCallbackUserData = user_data; } + typedef boost::signals2::signal focus_signal_t; + + boost::signals2::connection setFocusLostCallback( const focus_signal_t::slot_type& cb); + boost::signals2::connection setFocusReceivedCallback(const focus_signal_t::slot_type& cb); + boost::signals2::connection setFocusChangedCallback(const focus_signal_t::slot_type& cb); + boost::signals2::connection setTopLostCallback(const focus_signal_t::slot_type& cb); // These were brought up the hierarchy from LLView so that we don't have to use dynamic_cast when dealing with keyboard focus. virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); + virtual void onTopLost(); // called when registered as top ctrl and user clicks elsewhere protected: virtual void onFocusReceived(); virtual void onFocusLost(); - void (*mFocusLostCallback)( LLFocusableElement* caller, void* userdata ); - void (*mFocusReceivedCallback)( LLFocusableElement* ctrl, void* userdata ); - void (*mFocusChangedCallback)( LLFocusableElement* ctrl, void* userdata ); - void* mFocusCallbackUserData; + focus_signal_t* mFocusLostCallback; + focus_signal_t* mFocusReceivedCallback; + focus_signal_t* mFocusChangedCallback; + focus_signal_t* mTopLostCallback; }; @@ -76,7 +74,7 @@ class LLFocusMgr { public: LLFocusMgr(); - ~LLFocusMgr() { mFocusHistory.clear(); } + ~LLFocusMgr(); // Mouse Captor void setMouseCapture(LLMouseHandler* new_captor); // new_captor = NULL to release the mouse. @@ -93,7 +91,7 @@ public: BOOL getKeystrokesOnly() { return mKeystrokesOnly; } void setKeystrokesOnly(BOOL keystrokes_only) { mKeystrokesOnly = keystrokes_only; } - F32 getFocusTime() const { return mFocusTimer.getElapsedTimeF32(); } + F32 getFocusTime() const { return mFocusFlashTimer.getElapsedTimeF32(); } F32 getFocusFlashAmt() const; S32 getFocusFlashWidth() const { return llround(lerp(1.f, 3.f, getFocusFlashAmt())); } LLColor4 getFocusColor() const; @@ -121,6 +119,9 @@ public: void unlockFocus(); BOOL focusLocked() const { return mLockedView != NULL; } + + struct Impl; + private: LLUICtrl* mLockedView; @@ -132,23 +133,15 @@ private: LLFocusableElement* mLastKeyboardFocus; // who last had focus LLFocusableElement* mDefaultKeyboardFocus; BOOL mKeystrokesOnly; - + // Top View LLUICtrl* mTopCtrl; - LLFrameTimer mFocusTimer; - F32 mFocusWeight; + LLFrameTimer mFocusFlashTimer; BOOL mAppHasFocus; - typedef std::map, LLHandle > focus_history_map_t; - focus_history_map_t mFocusHistory; - - #ifdef _DEBUG - std::string mMouseCaptorName; - std::string mKeyboardFocusName; - std::string mTopCtrlName; - #endif + Impl * mImpl; }; extern LLFocusMgr gFocusMgr; diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index b41263d97..547ff4088 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -42,12 +42,38 @@ const U32 KEYWORD_FILE_CURRENT_VERSION = 2; -inline BOOL LLKeywordToken::isHead(const llwchar* s) const +inline BOOL LLKeywordToken::isHead(const llwchar* s, bool search_end_c_comment) const { // strncmp is much faster than string compare - BOOL res = TRUE; const llwchar* t = mToken.c_str(); S32 len = mToken.size(); + if (search_end_c_comment && len == 2 && t[0] == '/' && t[1] == '*') + { + // Special case for C-like */ end comment token + if (s[0] == '*' && s[1] == '/') + { + return TRUE; + } + else + { + return FALSE; + } + } + for (S32 i = 0; i < len; i++) + { + if (s[i] != t[i]) + { + return FALSE; + } + } + return TRUE; +} + +inline BOOL LLKeywordToken::isTail(const llwchar* s) const +{ + BOOL res = TRUE; + const llwchar* t = mDelimiter.c_str(); + S32 len = mDelimiter.size(); for (S32 i=0; i* seg_list, const LLWS const llwchar* base = wtext.c_str(); const llwchar* cur = base; - const llwchar* line = NULL; + //const llwchar* line = NULL; while( *cur ) { @@ -265,7 +312,7 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS } // Start of a new line - line = cur; + //line = cur; // Skip white space while( *cur && isspace(*cur) && (*cur != '\n') ) @@ -342,15 +389,15 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS seg_start = cur - base; cur += cur_delimiter->getLength(); - if( cur_delimiter->getType() == LLKeywordToken::TWO_SIDED_DELIMITER ) + //if( cur_delimiter->getType() == LLKeywordToken::TWO_SIDED_DELIMITER ) + LLKeywordToken::TOKEN_TYPE type = cur_delimiter->getType(); + if( type == LLKeywordToken::TWO_SIDED_DELIMITER || type == LLKeywordToken::TWO_SIDED_DELIMITER_ESC ) { - LLWString str = cur_delimiter->getToken(); - std::reverse(str.begin(),str.end()); //Flip the delim around (/* changes to */) - LLKeywordToken reverse_delimiter(cur_delimiter->getType(),cur_delimiter->getColor(),str,cur_delimiter->getToolTip()); - while( *cur && !reverse_delimiter.isHead(cur)) + //llassert( cur_delimiter->getDelimiter() != NULL ); + while( *cur && !cur_delimiter->isTail(cur) ) { // Check for an escape sequence. - if (*cur == '\\') + if (type == LLKeywordToken::TWO_SIDED_DELIMITER_ESC && *cur == '\\') { // Count the number of backslashes. S32 num_backslashes = 0; @@ -361,7 +408,7 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS cur++; } // Is the next character the end delimiter? - if (reverse_delimiter.isHead(cur)) + if (cur_delimiter->isTail(cur)) { // Is there was an odd number of backslashes, then this delimiter // does not end the sequence. @@ -387,7 +434,7 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS if( *cur ) { cur += cur_delimiter->getLength(); - seg_end = seg_start + between_delimiters + 2 * cur_delimiter->getLength(); + seg_end = seg_start + between_delimiters + cur_delimiter->getLength() + cur_delimiter->getLength2(); } else { @@ -420,10 +467,10 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS // check against words llwchar prev = cur > base ? *(cur-1) : 0; - if( !isalnum( prev ) && (prev != '_') ) + if( !isalnum( prev ) && (prev != '_') && (prev != '#')) { const llwchar* p = cur; - while( isalnum( *p ) || (*p == '_') ) + while( isalnum( *p ) || (*p == '_') || (*p == '#') ) { p++; } diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h index 38f5e993c..5c55157ac 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -46,23 +46,27 @@ class LLTextSegment; class LLKeywordToken { public: - enum TOKEN_TYPE { WORD, LINE, TWO_SIDED_DELIMITER, ONE_SIDED_DELIMITER }; + enum TOKEN_TYPE { WORD, LINE, TWO_SIDED_DELIMITER, ONE_SIDED_DELIMITER, TWO_SIDED_DELIMITER_ESC }; - LLKeywordToken( TOKEN_TYPE type, const LLColor3& color, const LLWString& token, const LLWString& tool_tip ) + LLKeywordToken( TOKEN_TYPE type, const LLColor3& color, const LLWString& token, const LLWString& tool_tip, const LLWString& delimiter ) : mType( type ), mToken( token ), mColor( color ), - mToolTip( tool_tip ) + mToolTip( tool_tip ), + mDelimiter( delimiter ) // right delimiter { } S32 getLength() const { return mToken.size(); } - BOOL isHead(const llwchar* s) const; + S32 getLength2() const { return mDelimiter.size(); } + BOOL isHead(const llwchar* s, bool search_end_c_comment = false) const; + BOOL isTail(const llwchar* s) const; const LLWString& getToken() const { return mToken; } const LLColor3& getColor() const { return mColor; } TOKEN_TYPE getType() const { return mType; } const LLWString& getToolTip() const { return mToolTip; } + const LLWString& getDelimiter() const { return mDelimiter; } #ifdef _DEBUG void dump(); @@ -73,6 +77,7 @@ private: LLWString mToken; LLColor3 mColor; LLWString mToolTip; + LLWString mDelimiter; }; class LLKeywords @@ -90,7 +95,8 @@ public: void addToken(LLKeywordToken::TOKEN_TYPE type, const std::string& key, const LLColor3& color, - const std::string& tool_tip = LLStringUtil::null); + const std::string& tool_tip = LLStringUtil::null, + const std::string& delimiter = LLStringUtil::null); typedef std::map word_token_map_t; typedef word_token_map_t::const_iterator keyword_iterator_t; diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 60f8f9934..f54d2c761 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -104,7 +104,6 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect, : LLUICtrl( name, rect, TRUE, commit_callback, userdata, FOLLOWS_TOP | FOLLOWS_LEFT ), mMaxLengthBytes(max_length_bytes), - mPopupMenuHandle(), mCursorPos( 0 ), mScrollHPos( 0 ), mTextPadLeft(0), @@ -140,7 +139,8 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect, mHaveHistory(FALSE), mImage( sImage ), mReplaceNewlinesWithSpaces( TRUE ), - mSpellCheckable( FALSE ) + mSpellCheckable( FALSE ), + mContextMenuHandle() { llassert( max_length_bytes > 0 ); @@ -156,7 +156,8 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect, mGLFont = LLFontGL::getFontSansSerifSmall(); } - setFocusLostCallback(focus_lost_callback); + if(focus_lost_callback) + setFocusLostCallback(boost::bind(focus_lost_callback,_1,(void*)NULL)); setTextPadding(0, 0); @@ -185,35 +186,30 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect, { menu = new LLMenuGL(LLStringUtil::null); }*/ - menu->append(new LLMenuItemCallGL("Cut", context_cut, NULL, this)); - menu->append(new LLMenuItemCallGL("Copy", context_copy, NULL, this)); - menu->append(new LLMenuItemCallGL("Paste", context_paste, NULL, this)); - menu->append(new LLMenuItemCallGL("Delete", context_delete, NULL, this)); - menu->append(new LLMenuItemCallGL("Select All", context_selectall, NULL, this)); - menu->appendSeparator("Spelsep"); + menu->addChild(new LLMenuItemCallGL("Cut", context_cut, NULL, this)); + menu->addChild(new LLMenuItemCallGL("Copy", context_copy, NULL, this)); + menu->addChild(new LLMenuItemCallGL("Paste", context_paste, NULL, this)); + menu->addChild(new LLMenuItemCallGL("Delete", context_delete, NULL, this)); + menu->addChild(new LLMenuItemCallGL("Select All", context_selectall, NULL, this)); + menu->addSeparator(); //menu->setBackgroundColor(gColors.getColor("MenuPopupBgColor")); menu->setCanTearOff(FALSE); menu->setVisible(FALSE); - mPopupMenuHandle = menu->getHandle(); + setContextMenu(menu); } - - + LLLineEditor::~LLLineEditor() { mCommitOnFocusLost = FALSE; + // calls onCommit() while LLLineEditor still valid gFocusMgr.releaseFocusIfNeeded( this ); - - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } - LLView::deleteViewByHandle(mPopupMenuHandle); } void LLLineEditor::onFocusReceived() { + gEditMenuHandler = this; LLUICtrl::onFocusReceived(); updateAllowingLanguageInput(); } @@ -645,105 +641,6 @@ BOOL LLLineEditor::handleDoubleClick(S32 x, S32 y, MASK mask) return TRUE; } - -BOOL LLLineEditor::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - setFocus(TRUE); - - //setCursorAtLocalPos( x); - S32 wordStart = 0; - S32 wordLen = 0; - S32 pos = calculateCursorFromMouse(x); - - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu) - { - if(menu->isOpen()) - { - menu->setVisible(FALSE); - } - for (int i = 0;i<(int)suggestionMenuItems.size();i++) - { - SpellMenuBind * tempBind = suggestionMenuItems[i]; - if(tempBind) - { - menu->remove((LLMenuItemCallGL *)tempBind->menuItem); - ((LLMenuItemCallGL *)tempBind->menuItem)->die(); - //delete tempBind->menuItem; - //tempBind->menuItem = NULL; - delete tempBind; - } - } - suggestionMenuItems.clear(); - - // spell_check="true" in xui - menu->setItemVisible("Spelsep", !mReadOnly && mSpellCheckable); - if (!mReadOnly && mSpellCheckable) - { - // search for word matches - bool is_word_part = getWordBoundriesAt(pos, &wordStart, &wordLen); - if (is_word_part) - { - const LLWString& text = mText.getWString(); - std::string selectedWord(std::string(text.begin(), text.end()).substr(wordStart,wordLen)); - - if (!glggHunSpell->isSpelledRight(selectedWord)) - { - //misspelled word here, and you have just right clicked on it! - std::vector suggs = glggHunSpell->getSuggestionList(selectedWord); - - for (int i = 0; i<(int)suggs.size() ;i++) - { - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - tempStruct->word = suggs[i]; - tempStruct->wordPositionEnd = wordStart + wordLen; - tempStruct->wordPositionStart=wordStart; - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - tempStruct->word, spell_correct, NULL, tempStruct); - //new LLMenuItemCallGL("Select All", context_selectall, NULL, this)); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->append(suggMenuItem); - } - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - tempStruct->word = selectedWord; - tempStruct->wordPositionEnd = wordStart + wordLen; - tempStruct->wordPositionStart=wordStart; - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - "Add Word", spell_add, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->append(suggMenuItem); - } - } - - SpellMenuBind * tempStruct = new SpellMenuBind; - tempStruct->origin = this; - if (glggHunSpell->getSpellCheckHighlight()) - { - tempStruct->word = "Hide Misspellings"; - } - else - { - tempStruct->word = "Show Misspellings"; - } - LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( - tempStruct->word, spell_show, NULL, tempStruct); - tempStruct->menuItem = suggMenuItem; - suggestionMenuItems.push_back(tempStruct); - menu->append(suggMenuItem); - } - - mLastContextMenuX = x; - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, menu, x, y); - } - return TRUE; -} - BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask) { // Check first whether the "clear search" button wants to deal with this. @@ -835,6 +732,16 @@ BOOL LLLineEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask) return TRUE; } +BOOL LLLineEditor::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + setFocus(TRUE); + if (!LLUICtrl::handleRightMouseDown(x, y, mask)) + { + showContextMenu(x, y); + } + return TRUE; +} + BOOL LLLineEditor::handleHover(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; @@ -1615,7 +1522,7 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask ) // SL-51858: Key presses are not being passed to the Popup menu. // A proper fix is non-trivial so instead just close the menu. - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + LLMenuGL* menu = (LLMenuGL*)mContextMenuHandle.get(); if (menu && menu->isOpen()) { LLMenuGL::sMenuContainer->hideMenus(); @@ -1697,7 +1604,7 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char) { // SL-51858: Key presses are not being passed to the Popup menu. // A proper fix is non-trivial so instead just close the menu. - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + LLMenuGL* menu = (LLMenuGL*)mContextMenuHandle.get(); if (menu && menu->isOpen()) { LLMenuGL::sMenuContainer->hideMenus(); @@ -2060,7 +1967,7 @@ void LLLineEditor::draw() // Make sure the IME is in the right place S32 pixels_after_scroll = findPixelNearestPos(); // RCalculcate for IME position - LLRect screen_pos = getScreenRect(); + LLRect screen_pos = calcScreenRect(); LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - UI_LINEEDITOR_V_PAD ); ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]); @@ -3069,6 +2976,121 @@ LLWString LLLineEditor::getConvertedText() const return text; } +void LLLineEditor::showContextMenu(S32 x, S32 y) +{ + LLMenuGL* menu = static_cast(mContextMenuHandle.get()); + + if (menu) + { + gEditMenuHandler = this; + + /*S32 screen_x, screen_y; + localPointToScreen(x, y, &screen_x, &screen_y); + menu->show(screen_x, screen_y);*/ + + + //setCursorAtLocalPos( x); + S32 wordStart = 0; + S32 wordLen = 0; + S32 pos = calculateCursorFromMouse(x); + + LLMenuGL* menu = (LLMenuGL*)mContextMenuHandle.get(); + if (menu) + { + if(menu->isOpen()) + { + menu->setVisible(FALSE); + } + for (int i = 0;i<(int)suggestionMenuItems.size();i++) + { + SpellMenuBind * tempBind = suggestionMenuItems[i]; + if(tempBind) + { + menu->removeChild((LLMenuItemCallGL *)tempBind->menuItem); + ((LLMenuItemCallGL *)tempBind->menuItem)->die(); + //delete tempBind->menuItem; + //tempBind->menuItem = NULL; + delete tempBind; + } + } + suggestionMenuItems.clear(); + + // spell_check="true" in xui + menu->setItemVisible("Spelsep", !mReadOnly && mSpellCheckable); + if (!mReadOnly && mSpellCheckable) + { + // search for word matches + bool is_word_part = getWordBoundriesAt(pos, &wordStart, &wordLen); + if (is_word_part) + { + const LLWString& text = mText.getWString(); + std::string selectedWord(std::string(text.begin(), text.end()).substr(wordStart,wordLen)); + + if (!glggHunSpell->isSpelledRight(selectedWord)) + { + //misspelled word here, and you have just right clicked on it! + std::vector suggs = glggHunSpell->getSuggestionList(selectedWord); + + for (int i = 0; i<(int)suggs.size() ;i++) + { + SpellMenuBind * tempStruct = new SpellMenuBind; + tempStruct->origin = this; + tempStruct->word = suggs[i]; + tempStruct->wordPositionEnd = wordStart + wordLen; + tempStruct->wordPositionStart=wordStart; + LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( + tempStruct->word, spell_correct, NULL, tempStruct); + //new LLMenuItemCallGL("Select All", context_selectall, NULL, this)); + tempStruct->menuItem = suggMenuItem; + suggestionMenuItems.push_back(tempStruct); + menu->addChild(suggMenuItem); + } + SpellMenuBind * tempStruct = new SpellMenuBind; + tempStruct->origin = this; + tempStruct->word = selectedWord; + tempStruct->wordPositionEnd = wordStart + wordLen; + tempStruct->wordPositionStart=wordStart; + LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( + "Add Word", spell_add, NULL, tempStruct); + tempStruct->menuItem = suggMenuItem; + suggestionMenuItems.push_back(tempStruct); + menu->addChild(suggMenuItem); + } + } + + SpellMenuBind * tempStruct = new SpellMenuBind; + tempStruct->origin = this; + if (glggHunSpell->getSpellCheckHighlight()) + { + tempStruct->word = "Hide Misspellings"; + } + else + { + tempStruct->word = "Show Misspellings"; + } + LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL( + tempStruct->word, spell_show, NULL, tempStruct); + tempStruct->menuItem = suggMenuItem; + suggestionMenuItems.push_back(tempStruct); + menu->addChild(suggMenuItem); + } + + mLastContextMenuX = x; + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, menu, x, y); + } + } +} + +void LLLineEditor::setContextMenu(LLMenuGL* new_context_menu) +{ + if (new_context_menu) + mContextMenuHandle = new_context_menu->getHandle(); + else + mContextMenuHandle.markDead(); +} + static LLRegisterWidget r2("search_editor"); diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 6c6ca2884..280fafbca 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -56,6 +56,7 @@ class LLFontGL; class LLLineEditorRollback; class LLButton; +class LLMenuGL; typedef BOOL (*LLLinePrevalidateFunc)(const LLWString &wstr); @@ -79,6 +80,9 @@ public: LLViewBorder::EStyle border_style = LLViewBorder::STYLE_LINE, S32 border_thickness = 1); +protected: + void showContextMenu(S32 x, S32 y); +public: virtual ~LLLineEditor(); virtual LLXMLNodePtr getXML(bool save_children = true) const; @@ -252,7 +256,9 @@ public: void updateHistory(); // stores current line in history void setReplaceNewlinesWithSpaces(BOOL replace); - + + void setContextMenu(LLMenuGL* new_context_menu); + private: // private helper methods @@ -285,7 +291,6 @@ private: virtual S32 getPreeditFontSize() const; protected: - LLHandle mPopupMenuHandle; LLUIString mText; // The string being edited. std::string mPrevText; // Saved string for 'ESC' revert LLUIString mLabel; // text label that is visible when no user text provided @@ -359,6 +364,8 @@ protected: std::vector mPreeditPositions; LLPreeditor::standouts_t mPreeditStandouts; + LLHandle mContextMenuHandle; + private: // Utility on top of LLUI::getUIImage, looks up a named image in a given XML node and returns it if possible // or returns a given default image if anything in the process fails. diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 21a6711c4..cce9eb172 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -46,20 +46,21 @@ #include "llmenugl.h" +#include "llgl.h" #include "llmath.h" #include "llrender.h" #include "llfocusmgr.h" -#include "llfont.h" #include "llcoord.h" #include "llwindow.h" #include "llcriticaldamp.h" #include "lluictrlfactory.h" +#include "llbutton.h" #include "llfontgl.h" #include "llresmgr.h" +#include "lltrans.h" #include "llui.h" -#include "lltrans.h" #include "llstl.h" #include "v2math.h" @@ -102,10 +103,10 @@ const std::string SEPARATOR_LABEL( "-----------" ); const std::string VERTICAL_SEPARATOR_LABEL( "|" ); const std::string TEAROFF_SEPARATOR_LABEL( "~~~~~~~~~~~" ); -const std::string BOOLEAN_TRUE_PREFIX( "\xE2\x9C\x94" ); // U+2714 HEAVY CHECK MARK -const std::string BRANCH_SUFFIX( "\xE2\x96\xB6" ); // U+25B6 BLACK RIGHT-POINTING TRIANGLE -const std::string ARROW_UP ("^^^^^^^"); -const std::string ARROW_DOWN("vvvvvvv"); +const std::string LLMenuGL::BOOLEAN_TRUE_PREFIX( "\xE2\x9C\x94" ); // U+2714 HEAVY CHECK MARK +const std::string LLMenuGL::BRANCH_SUFFIX( "\xE2\x96\xB6" ); // U+25B6 BLACK RIGHT-POINTING TRIANGLE +const std::string LLMenuGL::ARROW_UP ("^^^^^^^"); +const std::string LLMenuGL::ARROW_DOWN("vvvvvvv"); const F32 MAX_MOUSE_SLOPE_SUB_MENU = 0.9f; @@ -135,21 +136,31 @@ const F32 ACTIVATE_HIGHLIGHT_TIME = 0.3f; // Default constructor LLMenuItemGL::LLMenuItemGL( const std::string& name, const std::string& label, KEY key, MASK mask ) : - LLView( name, TRUE ), + LLUICtrl( name, LLRect(), TRUE, NULL, NULL ), mJumpKey(KEY_NONE), - mAcceleratorKey( key ), - mAcceleratorMask( mask ), mAllowKeyRepeat(FALSE), mHighlight( FALSE ), mGotHover( FALSE ), mBriefItem( FALSE ), - mFont( LLFontGL::getFontSansSerif() ), mStyle(LLFontGL::NORMAL), - mDrawTextDisabled( FALSE ) + mDrawTextDisabled( FALSE ), + mFont( LLFontGL::getFontSansSerif() ), + mAcceleratorKey( key ), + mAcceleratorMask( mask ), + mLabel( label ), + mEnabledColor( sEnabledColor ), + mDisabledColor( sDisabledColor ), + mHighlightBackground( sHighlightBackground ), + mHighlightForeground( sHighlightForeground ) { setLabel( label ); } +LLMenuItemGL::~LLMenuItemGL() +{ + lldebugs << "Menu destroyed:" << this->getName() << llendl; +}; + // virtual LLXMLNodePtr LLMenuItemGL::getXML(bool save_children) const { @@ -192,6 +203,20 @@ LLXMLNodePtr LLMenuItemGL::getXML(bool save_children) const return node; } + +//virtual +void LLMenuItemGL::setValue(const LLSD& value) +{ + setLabel(value.asString()); +} + +//virtual +LLSD LLMenuItemGL::getValue() const +{ + return getLabel(); +} + +//virtual BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask) { if( getEnabled() && (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) ) @@ -209,6 +234,26 @@ BOOL LLMenuItemGL::handleHover(S32 x, S32 y, MASK mask) return TRUE; } +//virtual +BOOL LLMenuItemGL::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + return LLUICtrl::handleRightMouseDown(x,y,mask); +} + +//virtual +BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask) +{ + // If this event came from a right-click context menu spawn, + // process as a left-click to allow menu items to be hit + if (LLMenuHolderGL::sContextMenuSpawnPos.mX != S32_MAX + || LLMenuHolderGL::sContextMenuSpawnPos.mY != S32_MAX) + { + BOOL handled = handleMouseUp(x, y, mask); + return handled; + } + return LLUICtrl::handleRightMouseUp(x,y,mask); +} + // This function checks to see if the accelerator key is already in use; // if not, it will be added to the list BOOL LLMenuItemGL::addToAcceleratorList(std::list *listp) @@ -313,9 +358,20 @@ U32 LLMenuItemGL::getNominalHeight( void ) const return llround(mFont->getLineHeight()) + MENU_ITEM_PADDING; } +//virtual +void LLMenuItemGL::setBriefItem(BOOL brief) +{ + mBriefItem = brief; +} + +//virtual +BOOL LLMenuItemGL::isBriefItem() const +{ + return mBriefItem; +} // Get the parent menu for this item -LLMenuGL* LLMenuItemGL::getMenu() +LLMenuGL* LLMenuItemGL::getMenu() const { return (LLMenuGL*) getParent(); } @@ -339,7 +395,7 @@ U32 LLMenuItemGL::getNominalWidth( void ) const if( KEY_NONE != mAcceleratorKey ) { - width += ACCEL_PAD_PIXELS; + width += getMenu()->getShortcutPad(); std::string temp; appendAcceleratorString( temp ); width += mFont->getWidth( temp ); @@ -359,8 +415,10 @@ void LLMenuItemGL::buildDrawLabel( void ) void LLMenuItemGL::doIt( void ) { - // close all open menus by default - // if parent menu is actually visible (and we are not triggering menu item via accelerator) + // Check torn-off status to allow left-arrow keyboard navigation back + // to parent menu. + // Also, don't hide if item triggered by keyboard shortcut (and hence + // parent not visible). if (!getMenu()->getTornOff() && getMenu()->getVisible()) { @@ -375,6 +433,12 @@ void LLMenuItemGL::doIt( void ) { getMenu()->clearHoverItem(); } + + if (mHighlight != highlight) + { + //dirtyRect(); + } + mHighlight = highlight; } @@ -413,25 +477,30 @@ BOOL LLMenuItemGL::handleKeyHere( KEY key, MASK mask ) return FALSE; } -BOOL LLMenuItemGL::handleMouseUp( S32 x, S32 y, MASK ) +BOOL LLMenuItemGL::handleMouseUp( S32 x, S32 y, MASK mask) { // switch to mouse navigation mode LLMenuGL::setKeyboardMode(FALSE); doIt(); make_ui_sound("UISndClickRelease"); - return TRUE; + return LLView::handleMouseUp(x, y, mask); } -BOOL LLMenuItemGL::handleMouseDown( S32 x, S32 y, MASK ) +BOOL LLMenuItemGL::handleMouseDown( S32 x, S32 y, MASK mask) { // switch to mouse navigation mode LLMenuGL::setKeyboardMode(FALSE); setHighlight(TRUE); - return TRUE; + return LLView::handleMouseDown(x, y, mask); } +BOOL LLMenuItemGL::handleScrollWheel( S32 x, S32 y, S32 clicks ) +{ + // If the menu is scrollable let it handle the wheel event. + return FALSE;//!getMenu()->isScrollable(); +} void LLMenuItemGL::draw( void ) { @@ -442,7 +511,11 @@ void LLMenuItemGL::draw( void ) // let disabled items be highlighted, just don't draw them as such if( getEnabled() && getHighlight() && !mBriefItem) { - gGL.color4fv( sHighlightBackground.mV ); + int debug_count = 0; + if (dynamic_cast(this)) + debug_count++; + gGL.color4fv( mHighlightBackground.mV ); + gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 ); } @@ -456,15 +529,15 @@ void LLMenuItemGL::draw( void ) if ( getEnabled() && getHighlight() ) { - color = sHighlightForeground; + color = mHighlightForeground; } else if( getEnabled() && !mDrawTextDisabled ) { - color = sEnabledColor; + color = mEnabledColor; } else { - color = sDisabledColor; + color = mDisabledColor; } // Draw the text on top. @@ -489,7 +562,7 @@ void LLMenuItemGL::draw( void ) } if( !mDrawBranchLabel.empty() ) { - mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, + mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, (!getEnabled() || getHighlight()) ? color : color % .7f, LLFontGL::RIGHT, LLFontGL::BOTTOM, mStyle, font_shadow, S32_MAX, S32_MAX, NULL, FALSE ); } } @@ -518,37 +591,29 @@ BOOL LLMenuItemGL::setLabelArg( const std::string& key, const LLStringExplicit& return TRUE; } +void LLMenuItemGL::handleVisibilityChange(BOOL new_visibility) +{ + if (getMenu()) + { + getMenu()->needsArrange(); + } + LLView::handleVisibilityChange(new_visibility); +} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLMenuItemSeparatorGL // // This class represents a separator. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLMenuItemSeparatorGL : public LLMenuItemGL -{ -public: - LLMenuItemSeparatorGL( const std::string &name = SEPARATOR_NAME ); - - virtual LLXMLNodePtr getXML(bool save_children = true) const; - - virtual std::string getType() const { return "separator"; } - - // doIt() - do the primary funcationality of the menu item. - virtual void doIt( void ) {} - - virtual void draw( void ); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - - virtual U32 getNominalHeight( void ) const { return SEPARATOR_HEIGHT_PIXELS; } -}; LLMenuItemSeparatorGL::LLMenuItemSeparatorGL( const std::string &name ) : - LLMenuItemGL( name, SEPARATOR_LABEL ) + LLMenuItemGL( name.empty() ? SEPARATOR_NAME : name, SEPARATOR_LABEL ) { } - +U32 LLMenuItemSeparatorGL::getNominalHeight( void ) const +{ + return SEPARATOR_HEIGHT_PIXELS; +} LLXMLNodePtr LLMenuItemSeparatorGL::getXML(bool save_children) const { @@ -561,7 +626,7 @@ LLXMLNodePtr LLMenuItemSeparatorGL::getXML(bool save_children) const void LLMenuItemSeparatorGL::draw( void ) { - gGL.color4fv( getDisabledColor().mV ); + gGL.color4fv( mDisabledColor.mV ); const S32 y = getRect().getHeight() / 2; const S32 PAD = 6; gl_line_2d( PAD, y, getRect().getWidth() - PAD, y ); @@ -572,11 +637,14 @@ BOOL LLMenuItemSeparatorGL::handleMouseDown(S32 x, S32 y, MASK mask) LLMenuGL* parent_menu = getMenu(); if (y > getRect().getHeight() / 2) { - return parent_menu->handleMouseDown(x + getRect().mLeft, getRect().mTop + 1, mask); + // the menu items are in the child list in bottom up order + LLView* prev_menu_item = parent_menu->findNextSibling(this); + return prev_menu_item ? prev_menu_item->handleMouseDown(x, prev_menu_item->getRect().getHeight(), mask) : FALSE; } else { - return parent_menu->handleMouseDown(x + getRect().mLeft, getRect().mBottom - 1, mask); + LLView* next_menu_item = parent_menu->findPrevSibling(this); + return next_menu_item ? next_menu_item->handleMouseDown(x, 0, mask) : FALSE; } } @@ -585,11 +653,13 @@ BOOL LLMenuItemSeparatorGL::handleMouseUp(S32 x, S32 y, MASK mask) LLMenuGL* parent_menu = getMenu(); if (y > getRect().getHeight() / 2) { - return parent_menu->handleMouseUp(x + getRect().mLeft, getRect().mTop + 1, mask); + LLView* prev_menu_item = parent_menu->findNextSibling(this); + return prev_menu_item ? prev_menu_item->handleMouseUp(x, prev_menu_item->getRect().getHeight(), mask) : FALSE; } else { - return parent_menu->handleMouseUp(x + getRect().mLeft, getRect().mBottom - 1, mask); + LLView* next_menu_item = parent_menu->findPrevSibling(this); + return next_menu_item ? next_menu_item->handleMouseUp(x, 0, mask) : FALSE; } } @@ -608,7 +678,6 @@ BOOL LLMenuItemSeparatorGL::handleHover(S32 x, S32 y, MASK mask) } } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLMenuItemVerticalSeparatorGL // @@ -632,9 +701,8 @@ LLMenuItemVerticalSeparatorGL::LLMenuItemVerticalSeparatorGL( void ) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLMenuItemTearOffGL //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LLMenuItemTearOffGL::LLMenuItemTearOffGL(LLHandle parent_floater_handle) : - LLMenuItemGL(std::string("tear off"), TEAROFF_SEPARATOR_LABEL), - mParentHandle(parent_floater_handle) +LLMenuItemTearOffGL::LLMenuItemTearOffGL() : + LLMenuItemGL(std::string("tear off"), TEAROFF_SEPARATOR_LABEL) { } @@ -648,6 +716,35 @@ LLXMLNodePtr LLMenuItemTearOffGL::getXML(bool save_children) const return node; } +// Returns the first floater ancestor if there is one +LLFloater* LLMenuItemTearOffGL::getParentFloater() +{ + LLView* parent_view = getMenu(); + + while (parent_view) + { + if (dynamic_cast(parent_view)) + { + return dynamic_cast(parent_view); + } + + bool parent_is_menu = dynamic_cast(parent_view) && !dynamic_cast(parent_view); + + if (parent_is_menu) + { + // use menu parent + parent_view = dynamic_cast(parent_view)->getParentMenuItem(); + } + else + { + // just use regular view parent + parent_view = parent_view->getParent(); + } + } + + return NULL; +} + void LLMenuItemTearOffGL::doIt() { if (getMenu()->getTornOff()) @@ -663,9 +760,9 @@ void LLMenuItemTearOffGL::doIt() getMenu()->highlightNextItem(this); } - getMenu()->arrange(); + getMenu()->needsArrange(); - LLFloater* parent_floater = mParentHandle.get(); + LLFloater* parent_floater = getParentFloater(); LLFloater* tear_off_menu = LLTearOffMenu::create(getMenu()); if (tear_off_menu) @@ -680,7 +777,7 @@ void LLMenuItemTearOffGL::doIt() tear_off_menu->setFocus(TRUE); } } - LLMenuItemGL::doIt(); + LLMenuItemGL::onCommit(); } void LLMenuItemTearOffGL::draw() @@ -688,17 +785,17 @@ void LLMenuItemTearOffGL::draw() // disabled items can be highlighted, but shouldn't render as such if( getEnabled() && getHighlight() && !isBriefItem()) { - gGL.color4fv( getHighlightBGColor().mV ); + gGL.color4fv( mHighlightBackground.mV ); gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 ); } if (getEnabled()) { - gGL.color4fv( getEnabledColor().mV ); + gGL.color4fv( mEnabledColor.mV ); } else { - gGL.color4fv( getDisabledColor().mV ); + gGL.color4fv( mDisabledColor.mV ); } const S32 y = getRect().getHeight() / 3; const S32 PAD = 6; @@ -884,14 +981,21 @@ void LLMenuItemCallGL::doIt( void ) LLMenuItemGL::doIt(); } -void LLMenuItemCallGL::buildDrawLabel( void ) +void LLMenuItemCallGL::updateEnabled( void ) { - LLPointer fired_event = new LLEvent(this); - fireEvent(fired_event, "on_build"); if( mEnabledCallback ) { setEnabled( mEnabledCallback( mUserData ) ); } +} + +void LLMenuItemCallGL::buildDrawLabel( void ) +{ + updateEnabled(); + + LLPointer fired_event = new LLEvent(this); + fireEvent(fired_event, "on_build"); + if(mLabelCallback) { std::string label; @@ -901,16 +1005,18 @@ void LLMenuItemCallGL::buildDrawLabel( void ) LLMenuItemGL::buildDrawLabel(); } +BOOL LLMenuItemCallGL::handleKeyHere( KEY key, MASK mask ) +{ + return LLMenuItemGL::handleKeyHere(key, mask); +} + BOOL LLMenuItemCallGL::handleAcceleratorKey( KEY key, MASK mask ) { if( (!gKeyboard->getKeyRepeated(key) || getAllowKeyRepeat()) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) ) { LLPointer fired_event = new LLEvent(this); fireEvent(fired_event, "on_build"); - if( mEnabledCallback ) - { - setEnabled( mEnabledCallback( mUserData ) ); - } + updateEnabled(); if( !getEnabled() ) { if( mOnDisabledCallback ) @@ -971,7 +1077,7 @@ void LLMenuItemCheckGL::setValue(const LLSD& value) mChecked = value.asBoolean(); if(mChecked) { - mDrawBoolLabel = BOOLEAN_TRUE_PREFIX; + mDrawBoolLabel = LLMenuGL::BOOLEAN_TRUE_PREFIX; } else { @@ -1011,7 +1117,7 @@ void LLMenuItemCheckGL::buildDrawLabel( void ) { if(mChecked || (mCheckCallback && mCheckCallback( getUserData() ) ) ) { - mDrawBoolLabel = BOOLEAN_TRUE_PREFIX; + mDrawBoolLabel = LLMenuGL::BOOLEAN_TRUE_PREFIX; } else { @@ -1045,7 +1151,7 @@ void LLMenuItemToggleGL::buildDrawLabel( void ) { if( *mToggle ) { - mDrawBoolLabel = BOOLEAN_TRUE_PREFIX; + mDrawBoolLabel = LLMenuGL::BOOLEAN_TRUE_PREFIX; } else { @@ -1068,47 +1174,51 @@ void LLMenuItemToggleGL::doIt( void ) } -LLMenuItemBranchGL::LLMenuItemBranchGL( const std::string& name, const std::string& label, LLHandle branch, +LLMenuItemBranchGL::LLMenuItemBranchGL( const std::string& name, const std::string& label, LLHandle branch_handle, KEY key, MASK mask ) : - LLMenuItemGL( name, label, key, mask ), - mBranch( branch ) + LLMenuItemGL( name, label, key, mask ) { - if(!dynamic_cast(branch.get())) + LLMenuGL* branch = dynamic_cast(branch_handle.get()); + if(!branch) { llerrs << "Non-menu handle passed as branch reference." << llendl; } - if(getBranch()) + if (branch) { - getBranch()->setVisible( FALSE ); - getBranch()->setParentMenuItem(this); + mBranchHandle = branch->getHandle(); + branch->setVisible(FALSE); + branch->setParentMenuItem(this); } } LLMenuItemBranchGL::~LLMenuItemBranchGL() { - LLView::deleteViewByHandle(mBranch); + if (mBranchHandle.get()) + { + mBranchHandle.get()->die(); + } } // virtual LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const { - // richard: this is redundant with parent, remove - if (getBranch()) + LLMenuGL* branch = getBranch(); + if (branch) { - if(getBranch()->getName() == name) + if (branch->getName() == name) { - return getBranch(); + return branch; } // Always recurse on branches - LLView* child = getBranch()->getChildView(name, recurse, FALSE); + LLView* child = branch->getChildView(name, recurse, FALSE); if(child) { return child; } } - return LLView::getChildView(name, recurse, create_if_missing);; + return LLView::getChildView(name, recurse, create_if_missing); } // virtual @@ -1124,11 +1234,7 @@ BOOL LLMenuItemBranchGL::handleMouseUp(S32 x, S32 y, MASK mask) BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask) { - if(getBranch()) - { - return getBranch()->handleAcceleratorKey(key, mask); - } - return FALSE; + return getBranch() && getBranch()->handleAcceleratorKey(key, mask); } // virtual @@ -1147,19 +1253,21 @@ LLXMLNodePtr LLMenuItemBranchGL::getXML(bool save_children) const // if not, it will be added to the list BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list *listp) { - if(getBranch()) - { - U32 item_count = getBranch()->getItemCount(); - LLMenuItemGL *item; + LLMenuGL* branch = getBranch(); + if (!branch) + return FALSE; - while (item_count--) + U32 item_count = branch->getItemCount(); + LLMenuItemGL *item; + + while (item_count--) + { + if ((item = branch->getItem(item_count))) { - if ((item = getBranch()->getItem(item_count))) - { - return item->addToAcceleratorList(listp); - } + return item->addToAcceleratorList(listp); } } + return FALSE; } @@ -1171,7 +1279,7 @@ void LLMenuItemBranchGL::buildDrawLabel( void ) std::string st = mDrawAccelLabel; appendAcceleratorString( st ); mDrawAccelLabel = st; - mDrawBranchLabel = BRANCH_SUFFIX; + mDrawBranchLabel = LLMenuGL::BRANCH_SUFFIX; } // doIt() - do the primary functionality of the menu item. @@ -1181,7 +1289,7 @@ void LLMenuItemBranchGL::doIt( void ) // keyboard navigation automatically propagates highlight to sub-menu // to facilitate fast menu control via jump keys - if (getBranch() && LLMenuGL::getKeyboardMode() && !getBranch()->getHighlightedItem()) + if (LLMenuGL::getKeyboardMode() && getBranch()&& !getBranch()->getHighlightedItem()) { getBranch()->highlightNextItem(NULL); } @@ -1190,7 +1298,7 @@ void LLMenuItemBranchGL::doIt( void ) BOOL LLMenuItemBranchGL::handleKey(KEY key, MASK mask, BOOL called_from_parent) { BOOL handled = FALSE; - if (called_from_parent && getBranch()) + if (getBranch() && called_from_parent) { handled = getBranch()->handleKey(key, mask, called_from_parent); } @@ -1206,7 +1314,7 @@ BOOL LLMenuItemBranchGL::handleKey(KEY key, MASK mask, BOOL called_from_parent) BOOL LLMenuItemBranchGL::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) { BOOL handled = FALSE; - if (called_from_parent && getBranch()) + if (getBranch() && called_from_parent) { handled = getBranch()->handleUnicodeChar(uni_char, TRUE); } @@ -1222,21 +1330,21 @@ BOOL LLMenuItemBranchGL::handleUnicodeChar(llwchar uni_char, BOOL called_from_pa void LLMenuItemBranchGL::setHighlight( BOOL highlight ) { - if (highlight == getHighlight()) return; - - if(!getBranch()) - { + if (highlight == getHighlight()) return; - } - BOOL auto_open = getEnabled() && (!getBranch()->getVisible() || getBranch()->getTornOff()); + LLMenuGL* branch = getBranch(); + if (!branch) + return; + + BOOL auto_open = getEnabled() && (!branch->getVisible() || branch->getTornOff()); // torn off menus don't open sub menus on hover unless they have focus if (getMenu()->getTornOff() && !((LLFloater*)getMenu()->getParent())->hasFocus()) { auto_open = FALSE; } // don't auto open torn off sub-menus (need to explicitly active menu item to give them focus) - if (getBranch()->getTornOff()) + if (branch->getTornOff()) { auto_open = FALSE; } @@ -1250,14 +1358,14 @@ void LLMenuItemBranchGL::setHighlight( BOOL highlight ) } else { - if (getBranch()->getTornOff()) + if (branch->getTornOff()) { - ((LLFloater*)getBranch()->getParent())->setFocus(FALSE); - getBranch()->clearHoverItem(); + ((LLFloater*)branch->getParent())->setFocus(FALSE); + branch->clearHoverItem(); } else { - getBranch()->setVisible( FALSE ); + branch->setVisible( FALSE ); } } } @@ -1284,6 +1392,7 @@ void LLMenuItemBranchGL::handleVisibilityChange( BOOL new_visibility ) { if (new_visibility == FALSE && getBranch() && !getBranch()->getTornOff()) { + lldebugs << "Forcing branch to visible. Menu: " << getName() << " Branch: " << getBranch()->getName() << llendl; getBranch()->setVisible(FALSE); } LLMenuItemGL::handleVisibilityChange(new_visibility); @@ -1291,91 +1400,118 @@ void LLMenuItemBranchGL::handleVisibilityChange( BOOL new_visibility ) BOOL LLMenuItemBranchGL::handleKeyHere( KEY key, MASK mask ) { - if (getMenu()->getVisible() && getBranch() && getBranch()->getVisible() && key == KEY_LEFT) + LLMenuGL* branch = getBranch(); + if (!branch) + return LLMenuItemGL::handleKeyHere(key, mask); + + // an item is highlighted, my menu is open, and I have an active sub menu or we are in + // keyboard navigation mode + if (getHighlight() + && getMenu()->isOpen() + && (isActive() || LLMenuGL::getKeyboardMode())) { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); - - BOOL handled = getBranch()->clearHoverItem(); - if (getBranch()->getTornOff()) + if (branch->getVisible() && key == KEY_LEFT) { - ((LLFloater*)getBranch()->getParent())->setFocus(FALSE); + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); + + BOOL handled = branch->clearHoverItem(); + if (branch->getTornOff()) + { + ((LLFloater*)branch->getParent())->setFocus(FALSE); + } + if (handled && getMenu()->getTornOff()) + { + ((LLFloater*)getMenu()->getParent())->setFocus(TRUE); + } + return handled; } - if (handled && getMenu()->getTornOff()) - { - ((LLFloater*)getMenu()->getParent())->setFocus(TRUE); - } - return handled; - } - if (getHighlight() && - getMenu()->isOpen() && - key == KEY_RIGHT && getBranch() && !getBranch()->getHighlightedItem()) - { - // switch to keyboard navigation mode - LLMenuGL::setKeyboardMode(TRUE); - - LLMenuItemGL* itemp = getBranch()->highlightNextItem(NULL); - if (itemp) + if (key == KEY_RIGHT && !branch->getHighlightedItem()) { - return TRUE; + // switch to keyboard navigation mode + LLMenuGL::setKeyboardMode(TRUE); + + LLMenuItemGL* itemp = branch->highlightNextItem(NULL); + if (itemp) + { + return TRUE; + } } } - return LLMenuItemGL::handleKeyHere(key, mask); } +//virtual +BOOL LLMenuItemBranchGL::isActive() const +{ + return isOpen() && getBranch() && getBranch()->getHighlightedItem(); +} + +//virtual +BOOL LLMenuItemBranchGL::isOpen() const +{ + return getBranch() && getBranch()->isOpen(); +} + void LLMenuItemBranchGL::openMenu() { - if(!getBranch()) return; + LLMenuGL* branch = getBranch(); + if (!branch) + return; - if (getBranch()->getTornOff()) + if (branch->getTornOff()) { - gFloaterView->bringToFront((LLFloater*)getBranch()->getParent()); + gFloaterView->bringToFront((LLFloater*)branch->getParent()); // this might not be necessary, as torn off branches don't get focus and hence no highligth - getBranch()->highlightNextItem(NULL); + branch->highlightNextItem(NULL); } - else if( !getBranch()->getVisible() ) + else if( !branch->getVisible() ) { // get valid rectangle for menus const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect(); - getBranch()->arrange(); + branch->arrange(); - LLRect rect = getBranch()->getRect(); + LLRect branch_rect = branch->getRect(); // calculate root-view relative position for branch menu S32 left = getRect().mRight; S32 top = getRect().mTop - getRect().mBottom; - localPointToOtherView(left, top, &left, &top, getBranch()->getParent()); + localPointToOtherView(left, top, &left, &top, branch->getParent()); - rect.setLeftTopAndSize( left, top, - rect.getWidth(), rect.getHeight() ); + branch_rect.setLeftTopAndSize( left, top, + branch_rect.getWidth(), branch_rect.getHeight() ); - if (getBranch()->getCanTearOff()) + if (branch->getCanTearOff()) { - rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS); + branch_rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS); } - getBranch()->setRect( rect ); - S32 x = 0; - S32 y = 0; - getBranch()->localPointToOtherView( 0, 0, &x, &y, getBranch()->getParent() ); + branch->setRect( branch_rect ); + + // if branch extends outside of menu region change the direction it opens in + S32 x, y; S32 delta_x = 0; S32 delta_y = 0; - if( y < menu_region_rect.mBottom ) + branch->localPointToOtherView( 0, 0, &x, &y, branch->getParent() ); + + F32 center_y = top - (getRect().getHeight() / 2.f); + if( y < menu_region_rect.mBottom && center_y <= menu_region_rect.getCenterY()) { - delta_y = menu_region_rect.mBottom - y; + // open upwards if menu extends past bottom + // adjust by the height of the menu item branch since it is a submenu + delta_y = branch_rect.getHeight() - getRect().getHeight(); } - S32 menu_region_width = menu_region_rect.getWidth(); - if( x - menu_region_rect.mLeft > menu_region_width - rect.getWidth() ) + if( x + branch_rect.getWidth() > menu_region_rect.mRight ) { // move sub-menu over to left side - delta_x = llmax(-x, (-1 * (rect.getWidth() + getRect().getWidth()))); + delta_x = llmax(-x, ( -(branch_rect.getWidth() + getRect().getWidth()))); } - getBranch()->translate( delta_x, delta_y ); - getBranch()->setVisible( TRUE ); - getBranch()->getParent()->sendChildToFront(getBranch()); + branch->translate( delta_x, delta_y ); + + branch->setVisible( TRUE ); + branch->getParent()->sendChildToFront(branch); } } @@ -1540,6 +1676,7 @@ BOOL LLMenuItemBranchDownGL::handleMouseDown( S32 x, S32 y, MASK mask ) LLMenuGL::setKeyboardMode(FALSE); doIt(); make_ui_sound("UISndClick"); + setVisible(TRUE); return TRUE; } @@ -1566,7 +1703,7 @@ BOOL LLMenuItemBranchDownGL::handleKeyHere(KEY key, MASK mask) { BOOL menu_open = getBranch()->getVisible(); // don't do keyboard navigation of top-level menus unless in keyboard mode, or menu expanded - if (getHighlight() && getMenu()->getVisible() && (isActive() || LLMenuGL::getKeyboardMode())) + if (getHighlight() && getMenu()->isOpen() && (isActive() || LLMenuGL::getKeyboardMode())) { if (key == KEY_LEFT) { @@ -1635,7 +1772,7 @@ void LLMenuItemBranchDownGL::draw( void ) if( getHighlight() ) { - gGL.color4fv( getHighlightBGColor().mV ); + gGL.color4fv( mHighlightBackground.mV ); gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 ); } @@ -1648,20 +1785,19 @@ void LLMenuItemBranchDownGL::draw( void ) LLColor4 color; if (getHighlight()) { - color = getHighlightFGColor(); + color = mHighlightForeground; } else if( getEnabled() ) { - color = getEnabledColor(); + color = mEnabledColor; } else { - color = getDisabledColor(); + color = mDisabledColor; } getFont()->render( mLabel.getWString(), 0, (F32)getRect().getWidth() / 2.f, (F32)LABEL_BOTTOM_PAD_PIXELS, color, LLFontGL::HCENTER, LLFontGL::BOTTOM, getFontStyle(), font_shadow ); - // underline navigation key only when keyboard navigation has been initiated if (getMenu()->jumpKeysActive() && LLMenuGL::getKeyboardMode()) { @@ -1689,11 +1825,11 @@ void LLMenuItemBranchDownGL::draw( void ) static LLRegisterWidget r1("menu"); // Default constructor -LLMenuGL::LLMenuGL( const std::string& name, const std::string& label, LLHandle parent_floater_handle ) +LLMenuGL::LLMenuGL( const std::string& name, const std::string& label ) : LLUICtrl( name, LLRect(), FALSE, NULL, NULL ), mBackgroundColor( sDefaultBackgroundColor ), mBgVisible( TRUE ), - mParentMenuItem( NULL ), + mHasSelection( FALSE ), mLabel( label ), mDropShadowed( TRUE ), mHorizontalLayout( FALSE ), @@ -1705,20 +1841,21 @@ LLMenuGL::LLMenuGL( const std::string& name, const std::string& label, LLHandle< mTornOff(FALSE), mTearOffItem(NULL), mSpilloverBranch(NULL), + mFirstVisibleItem(NULL), mSpilloverMenu(NULL), - mParentFloaterHandle(parent_floater_handle), - mJumpKey(KEY_NONE) + mJumpKey(KEY_NONE), + mNeedsArrange(FALSE), + mShortcutPad(ACCEL_PAD_PIXELS) { mFadeTimer.stop(); - setCanTearOff(TRUE, parent_floater_handle); setTabStop(FALSE); } -LLMenuGL::LLMenuGL( const std::string& label, LLHandle parent_floater_handle ) +LLMenuGL::LLMenuGL( const std::string& label) : LLUICtrl( label, LLRect(), FALSE, NULL, NULL ), mBackgroundColor( sDefaultBackgroundColor ), mBgVisible( TRUE ), - mParentMenuItem( NULL ), + mHasSelection( FALSE ), mLabel( label ), mDropShadowed( TRUE ), mHorizontalLayout( FALSE ), @@ -1731,11 +1868,12 @@ LLMenuGL::LLMenuGL( const std::string& label, LLHandle parent_floater mTearOffItem(NULL), mSpilloverBranch(NULL), mSpilloverMenu(NULL), - mParentFloaterHandle(parent_floater_handle), - mJumpKey(KEY_NONE) + mFirstVisibleItem(NULL), + mJumpKey(KEY_NONE), + mNeedsArrange(FALSE), + mShortcutPad(ACCEL_PAD_PIXELS) { mFadeTimer.stop(); - setCanTearOff(TRUE, parent_floater_handle); setTabStop(FALSE); } @@ -1748,14 +1886,12 @@ LLMenuGL::~LLMenuGL( void ) mJumpKeys.clear(); } -void LLMenuGL::setCanTearOff(BOOL tear_off, LLHandle parent_floater_handle ) +void LLMenuGL::setCanTearOff(BOOL tear_off) { if (tear_off && mTearOffItem == NULL) { - mTearOffItem = new LLMenuItemTearOffGL(parent_floater_handle); - mItems.insert(mItems.begin(), mTearOffItem); - addChildAtEnd(mTearOffItem); - arrange(); + mTearOffItem = new LLMenuItemTearOffGL(); + addChild(mTearOffItem); } else if (!tear_off && mTearOffItem != NULL) { @@ -1763,7 +1899,7 @@ void LLMenuGL::setCanTearOff(BOOL tear_off, LLHandle parent_floater_h removeChild(mTearOffItem); delete mTearOffItem; mTearOffItem = NULL; - arrange(); + needsArrange(); } } @@ -1819,12 +1955,17 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory submenu->updateParent(parent); } } - else if (child->hasName(LL_MENU_ITEM_CALL_GL_TAG) || - child->hasName(LL_MENU_ITEM_CHECK_GL_TAG) || - child->hasName(LL_MENU_ITEM_SEPARATOR_GL_TAG)) + else if (child->hasName(LL_MENU_ITEM_SEPARATOR_GL_TAG)) { - LLMenuItemGL *item = NULL; - + std::string item_name; + child->getAttributeString("name", item_name); + LLMenuItemGL* separator = new LLMenuItemSeparatorGL(item_name); + addChild(separator); + } + else if(child->hasName(LL_MENU_ITEM_CALL_GL_TAG) || + child->hasName(LL_MENU_ITEM_CHECK_GL_TAG)) + { + // ITEM std::string type; std::string item_name; std::string source_label; @@ -1834,7 +1975,7 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory child->getAttributeString("type", type); child->getAttributeString("name", item_name); child->getAttributeString("label", source_label); - + // parse jump key out of label typedef boost::tokenizer > tokenizer; boost::char_separator sep("_"); @@ -1851,245 +1992,262 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory ++token_count; } - - if (child->hasName(LL_MENU_ITEM_SEPARATOR_GL_TAG)) + MASK mask = 0; + +#ifdef LL_DARWIN + // See if this Mac accelerator should really use the ctrl key and not get mapped to cmd + BOOL useMacCtrl = FALSE; + child->getAttributeBOOL("useMacCtrl", useMacCtrl); +#endif // LL_DARWIN + + std::string shortcut; + child->getAttributeString("shortcut", shortcut); + if (shortcut.find("control") != shortcut.npos) { - appendSeparator(item_name); - } - else - { - // ITEM - if (child->hasName(LL_MENU_ITEM_CALL_GL_TAG) || - child->hasName(LL_MENU_ITEM_CHECK_GL_TAG)) +#ifdef LL_DARWIN + if ( useMacCtrl ) { - MASK mask = 0; - -#ifdef LL_DARWIN - // See if this Mac accelerator should really use the ctrl key and not get mapped to cmd - BOOL useMacCtrl = FALSE; - child->getAttributeBOOL("useMacCtrl", useMacCtrl); + mask |= MASK_MAC_CONTROL; + } #endif // LL_DARWIN - - std::string shortcut; - child->getAttributeString("shortcut", shortcut); - if (shortcut.find("control") != shortcut.npos) - { -#ifdef LL_DARWIN - if ( useMacCtrl ) - { - mask |= MASK_MAC_CONTROL; - } -#endif // LL_DARWIN - mask |= MASK_CONTROL; - } - if (shortcut.find("alt") != shortcut.npos) - { - mask |= MASK_ALT; - } - if (shortcut.find("shift") != shortcut.npos) - { - mask |= MASK_SHIFT; - } - S32 pipe_pos = shortcut.rfind("|"); - std::string key_str = shortcut.substr(pipe_pos+1); + mask |= MASK_CONTROL; + } + if (shortcut.find("alt") != shortcut.npos) + { + mask |= MASK_ALT; + } + if (shortcut.find("shift") != shortcut.npos) + { + mask |= MASK_SHIFT; + } + S32 pipe_pos = shortcut.rfind("|"); + std::string key_str = shortcut.substr(pipe_pos+1); - KEY key = KEY_NONE; - LLKeyboard::keyFromString(key_str, &key); + KEY key = KEY_NONE; + LLKeyboard::keyFromString(key_str, &key); - LLMenuItemCallGL *new_item; - LLXMLNodePtr call_child; + LLMenuItemCallGL *new_item; + LLXMLNodePtr call_child; - if (child->hasName(LL_MENU_ITEM_CHECK_GL_TAG)) + if (child->hasName(LL_MENU_ITEM_CHECK_GL_TAG)) + { + std::string control_name; + child->getAttributeString("control_name", control_name); + + new_item = new LLMenuItemCheckGL(item_name, item_label, 0, 0, control_name, parent, 0, key, mask); + + for (call_child = child->getFirstChild(); call_child.notNull(); call_child = call_child->getNextSibling()) + { + if (call_child->hasName("on_check")) { + std::string callback_name; std::string control_name; - child->getAttributeString("control_name", control_name); - - new_item = new LLMenuItemCheckGL(item_name, item_label, 0, 0, control_name, parent, 0, key, mask); - - for (call_child = child->getFirstChild(); call_child.notNull(); call_child = call_child->getNextSibling()) + if (call_child->hasAttribute("function")) { - if (call_child->hasName("on_check")) - { - std::string callback_name; - std::string control_name; - if (call_child->hasAttribute("function")) - { - call_child->getAttributeString("function", callback_name); - - control_name = callback_name; - - std::string callback_data = item_name; - if (call_child->hasAttribute("userdata")) - { - call_child->getAttributeString("userdata", callback_data); - if (!callback_data.empty()) - { - control_name = llformat("%s(%s)", callback_name.c_str(), callback_data.c_str()); - } - } - - LLSD userdata; - userdata["control"] = control_name; - userdata["data"] = callback_data; - - LLSimpleListener* callback = parent->getListenerByName(callback_name); - - if (!callback) - { - lldebugs << "Ignoring \"on_check\" \"" << item_name << "\" because \"" << callback_name << "\" is not registered" << llendl; - continue; - } - - new_item->addListener(callback, "on_build", userdata); - } - else if (call_child->hasAttribute("control")) - { - call_child->getAttributeString("control", control_name); - } - else - { - continue; - } - LLControlVariable *control = parent->findControl(control_name); - if (!control) - { - parent->addBoolControl(control_name, FALSE); - } - ((LLMenuItemCheckGL*)new_item)->setCheckedControl(control_name, parent); - } - } - } - else - { - new_item = new LLMenuItemCallGL(item_name, item_label, 0, 0, 0, 0, key, mask); - } - - for (call_child = child->getFirstChild(); call_child.notNull(); call_child = call_child->getNextSibling()) - { - if (call_child->hasName("on_click")) - { - std::string callback_name; call_child->getAttributeString("function", callback_name); + control_name = callback_name; + std::string callback_data = item_name; if (call_child->hasAttribute("userdata")) { call_child->getAttributeString("userdata", callback_data); + if (!callback_data.empty()) + { + control_name = llformat("%s(%s)", callback_name.c_str(), callback_data.c_str()); + } } + LLSD userdata; + userdata["control"] = control_name; + userdata["data"] = callback_data; + LLSimpleListener* callback = parent->getListenerByName(callback_name); if (!callback) { - lldebugs << "Ignoring \"on_click\" \"" << item_name << "\" because \"" << callback_name << "\" is not registered" << llendl; + lldebugs << "Ignoring \"on_check\" \"" << item_name << "\" because \"" << callback_name << "\" is not registered" << llendl; continue; } - new_item->addListener(callback, "on_click", callback_data); + new_item->addListener(callback, "on_build", userdata); } - if (call_child->hasName("on_enable")) + else if (call_child->hasAttribute("control")) { - std::string callback_name; - std::string control_name; - if (call_child->hasAttribute("function")) - { - call_child->getAttributeString("function", callback_name); - - control_name = callback_name; - - std::string callback_data; - if (call_child->hasAttribute("userdata")) - { - call_child->getAttributeString("userdata", callback_data); - if (!callback_data.empty()) - { - control_name = llformat("%s(%s)", callback_name.c_str(), callback_data.c_str()); - } - } - - LLSD userdata; - userdata["control"] = control_name; - userdata["data"] = callback_data; - - LLSimpleListener* callback = parent->getListenerByName(callback_name); - - if (!callback) - { - lldebugs << "Ignoring \"on_enable\" \"" << item_name << "\" because \"" << callback_name << "\" is not registered" << llendl; - continue; - } - - new_item->addListener(callback, "on_build", userdata); - } - else if (call_child->hasAttribute("control")) - { - call_child->getAttributeString("control", control_name); - } - else - { - continue; - } - new_item->setEnabledControl(control_name, parent); + call_child->getAttributeString("control", control_name); } - if (call_child->hasName("on_visible")) + else { - std::string callback_name; - std::string control_name; - if (call_child->hasAttribute("function")) - { - call_child->getAttributeString("function", callback_name); - - control_name = callback_name; - - std::string callback_data; - if (call_child->hasAttribute("userdata")) - { - call_child->getAttributeString("userdata", callback_data); - if (!callback_data.empty()) - { - control_name = llformat("%s(%s)", callback_name.c_str(), callback_data.c_str()); - } - } - - LLSD userdata; - userdata["control"] = control_name; - userdata["data"] = callback_data; - - LLSimpleListener* callback = parent->getListenerByName(callback_name); - - if (!callback) - { - lldebugs << "Ignoring \"on_visible\" \"" << item_name << "\" because \"" << callback_name << "\" is not registered" << llendl; - continue; - } - - new_item->addListener(callback, "on_build", userdata); - } - else if (call_child->hasAttribute("control")) - { - call_child->getAttributeString("control", control_name); - } - else - { - continue; - } - new_item->setVisibleControl(control_name, parent); + continue; } + LLControlVariable *control = parent->findControl(control_name); + if (!control) + { + parent->addBoolControl(control_name, FALSE); + } + ((LLMenuItemCheckGL*)new_item)->setCheckedControl(control_name, parent); } - item = new_item; - item->setLabel(item_label); - if (jump_key != KEY_NONE) - item->setJumpKey(jump_key); - } - - if (item != NULL) - { - append(item); } } + else + { + new_item = new LLMenuItemCallGL(item_name, item_label, 0, 0, 0, 0, key, mask); + } + + for (call_child = child->getFirstChild(); call_child.notNull(); call_child = call_child->getNextSibling()) + { + if (call_child->hasName("on_click")) + { + std::string callback_name; + call_child->getAttributeString("function", callback_name); + + std::string callback_data = item_name; + if (call_child->hasAttribute("userdata")) + { + call_child->getAttributeString("userdata", callback_data); + } + + LLSimpleListener* callback = parent->getListenerByName(callback_name); + + if (!callback) + { + lldebugs << "Ignoring \"on_click\" \"" << item_name << "\" because \"" << callback_name << "\" is not registered" << llendl; + continue; + } + + new_item->addListener(callback, "on_click", callback_data); + } + if (call_child->hasName("on_enable")) + { + std::string callback_name; + std::string control_name; + if (call_child->hasAttribute("function")) + { + call_child->getAttributeString("function", callback_name); + + control_name = callback_name; + + std::string callback_data; + if (call_child->hasAttribute("userdata")) + { + call_child->getAttributeString("userdata", callback_data); + if (!callback_data.empty()) + { + control_name = llformat("%s(%s)", callback_name.c_str(), callback_data.c_str()); + } + } + + LLSD userdata; + userdata["control"] = control_name; + userdata["data"] = callback_data; + + LLSimpleListener* callback = parent->getListenerByName(callback_name); + + if (!callback) + { + lldebugs << "Ignoring \"on_enable\" \"" << item_name << "\" because \"" << callback_name << "\" is not registered" << llendl; + continue; + } + + new_item->addListener(callback, "on_build", userdata); + } + else if (call_child->hasAttribute("control")) + { + call_child->getAttributeString("control", control_name); + } + else + { + continue; + } + new_item->setEnabledControl(control_name, parent); + } + if (call_child->hasName("on_visible")) + { + std::string callback_name; + std::string control_name; + if (call_child->hasAttribute("function")) + { + call_child->getAttributeString("function", callback_name); + + control_name = callback_name; + + std::string callback_data; + if (call_child->hasAttribute("userdata")) + { + call_child->getAttributeString("userdata", callback_data); + if (!callback_data.empty()) + { + control_name = llformat("%s(%s)", callback_name.c_str(), callback_data.c_str()); + } + } + + LLSD userdata; + userdata["control"] = control_name; + userdata["data"] = callback_data; + + LLSimpleListener* callback = parent->getListenerByName(callback_name); + + if (!callback) + { + lldebugs << "Ignoring \"on_visible\" \"" << item_name << "\" because \"" << callback_name << "\" is not registered" << llendl; + continue; + } + + new_item->addListener(callback, "on_build", userdata); + } + else if (call_child->hasAttribute("control")) + { + call_child->getAttributeString("control", control_name); + } + else + { + continue; + } + new_item->setVisibleControl(control_name, parent); + } + } + new_item->setLabel(item_label); + if (jump_key != KEY_NONE) + new_item->setJumpKey(jump_key); + + append(new_item); } } +bool LLMenuGL::addChild(LLView* view, S32 tab_group) +{ + if (LLMenuGL* menup = dynamic_cast(view)) + { + lldebugs << "Adding menu " << menup->getName() << " to " << getName() << llendl; + appendMenu(menup); + return true; + } + else if (LLMenuItemGL* itemp = dynamic_cast(view)) + { + lldebugs << "Adding " << itemp->getName() << " to " << getName() << llendl; + append(itemp); + return true; + } + lldebugs << "Error adding unknown child '"<<(view ? view->getName() : std::string("NULL")) << "' to " << getName() << llendl; + return false; +} + +void LLMenuGL::removeChild( LLView* ctrl) +{ + // previously a dynamic_cast with if statement to check validity + // unfortunately removeChild is called by ~LLView, and at that point the + // object being deleted is no longer a LLMenuItemGL so a dynamic_cast will fail + LLMenuItemGL* itemp = static_cast(ctrl); + + item_list_t::iterator found_it = std::find(mItems.begin(), mItems.end(), (itemp)); + if (found_it != mItems.end()) + { + mItems.erase(found_it); + } + + return LLUICtrl::removeChild(ctrl); +} + // are we the childmost active menu and hence our jump keys should be enabled? // or are we a free-standing torn-off menu (which uses jump keys too) BOOL LLMenuGL::jumpKeysActive() @@ -2222,39 +2380,59 @@ void LLMenuGL::arrange( void ) // torn off menus are not constrained to the size of the screen U32 max_width = getTornOff() ? U32_MAX : menu_region_rect.getWidth(); - U32 max_height = getTornOff() ? U32_MAX : menu_region_rect.getHeight(); + U32 max_height = U32_MAX; + if (!getTornOff()) + { + max_height = getRect().mTop - menu_region_rect.mBottom; + if (menu_region_rect.mTop - getRect().mTop > (S32)max_height) + { + max_height = menu_region_rect.mTop - getRect().mTop; + } + } + // *FIX: create the item first and then ask for its dimensions? - S32 spillover_item_width = PLAIN_PAD_PIXELS + LLFontGL::getFontSansSerif()->getWidth( std::string("More") ); + S32 spillover_item_width = PLAIN_PAD_PIXELS + LLFontGL::getFontSansSerif()->getWidth( std::string("More") ); // *TODO: Translate S32 spillover_item_height = llround(LLFontGL::getFontSansSerif()->getLineHeight()) + MENU_ITEM_PADDING; + // Scrolling support + item_list_t::iterator first_visible_item_iter; + item_list_t::iterator first_hidden_item_iter = mItems.end(); + //S32 height_before_first_visible_item = -1; + //S32 visible_items_height = 0; + //U32 scrollable_items_cnt = 0; + if (mHorizontalLayout) { item_list_t::iterator item_iter; for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) { + // do first so LLMenuGLItemCall can call on_visible to determine if visible + (*item_iter)->buildDrawLabel(); + if ((*item_iter)->getVisible()) { if (!getTornOff() - && item_iter != mItems.begin() // Don't spillover the first item! + && *item_iter != mSpilloverBranch && width + (*item_iter)->getNominalWidth() > max_width - spillover_item_width) { // no room for any more items createSpilloverBranch(); - item_list_t::iterator spillover_iter; - for (spillover_iter = item_iter; spillover_iter != mItems.end(); ++spillover_iter) + std::vector items_to_remove; + std::copy(item_iter, mItems.end(), std::back_inserter(items_to_remove)); + std::vector::iterator spillover_iter; + for (spillover_iter= items_to_remove.begin(); spillover_iter != items_to_remove.end(); ++spillover_iter) { LLMenuItemGL* itemp = (*spillover_iter); removeChild(itemp); - mSpilloverMenu->appendNoArrange(itemp); // *NOTE:Mani Favor addChild() in merge with skinning + mSpilloverMenu->addChild(itemp); } - mSpilloverMenu->arrange(); // *NOTE: Mani Remove line in merge with skinning/viewer2.0 branch - mSpilloverMenu->updateParent(LLMenuGL::sMenuContainer); // *NOTE: Mani Remove line in merge with skinning/viewer2.0 branch - mItems.erase(item_iter, mItems.end()); - mItems.push_back(mSpilloverBranch); + addChild(mSpilloverBranch); + height = llmax(height, mSpilloverBranch->getNominalHeight()); width += mSpilloverBranch->getNominalWidth(); + break; } else @@ -2271,29 +2449,33 @@ void LLMenuGL::arrange( void ) item_list_t::iterator item_iter; for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) { + llassert_always((*item_iter)!=NULL); + // do first so LLMenuGLItemCall can call on_visible to determine if visible + (*item_iter)->buildDrawLabel(); + if ((*item_iter)->getVisible()) { if (!getTornOff() - && item_iter != mItems.begin() // Don't spillover the first item! + && *item_iter != mSpilloverBranch && height + (*item_iter)->getNominalHeight() > max_height - spillover_item_height) { // no room for any more items createSpilloverBranch(); - item_list_t::iterator spillover_iter; - for (spillover_iter= item_iter; spillover_iter != mItems.end(); ++spillover_iter) + std::vector items_to_remove; + std::copy(item_iter, mItems.end(), std::back_inserter(items_to_remove)); + std::vector::iterator spillover_iter; + for (spillover_iter= items_to_remove.begin(); spillover_iter != items_to_remove.end(); ++spillover_iter) { LLMenuItemGL* itemp = (*spillover_iter); removeChild(itemp); - mSpilloverMenu->appendNoArrange(itemp); // *NOTE:Mani Favor addChild() in merge with skinning + mSpilloverMenu->addChild(itemp); } - mSpilloverMenu->arrange(); // *NOTE: Mani Remove line in merge with skinning/viewer2.0 branch - mSpilloverMenu->updateParent(LLMenuGL::sMenuContainer); // *NOTE: Mani Remove line in merge with skinning/viewer2.0 branch - mItems.erase(item_iter, mItems.end()); - mItems.push_back(mSpilloverBranch); addChild(mSpilloverBranch); + height += mSpilloverBranch->getNominalHeight(); width = llmax( width, mSpilloverBranch->getNominalWidth() ); + break; } else @@ -2306,10 +2488,11 @@ void LLMenuGL::arrange( void ) } } - setRect(LLRect(getRect().mLeft, getRect().mBottom + height, getRect().mLeft + width, getRect().mBottom)); - S32 cur_height = (S32)llmin(max_height, height); + setRect(LLRect(getRect().mLeft, getRect().mTop, getRect().mLeft + width, getRect().mTop - cur_height)); + S32 cur_width = 0; + S32 offset = 0; item_list_t::iterator item_iter; for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) { @@ -2324,15 +2507,15 @@ void LLMenuGL::arrange( void ) } else { - rect.setLeftTopAndSize( 0, cur_height, width, (*item_iter)->getNominalHeight()); - cur_height -= (*item_iter)->getNominalHeight(); + rect.setLeftTopAndSize( 0 + offset, cur_height, width, (*item_iter)->getNominalHeight()); + if (offset == 0) + { + cur_height -= (*item_iter)->getNominalHeight(); + } } (*item_iter)->setRect( rect ); - (*item_iter)->buildDrawLabel(); } } - - cleanupSpilloverBranch(); } if (mKeepFixedSize) { @@ -2340,6 +2523,15 @@ void LLMenuGL::arrange( void ) } } +void LLMenuGL::arrangeAndClear( void ) +{ + if (mNeedsArrange) + { + arrange(); + mNeedsArrange = FALSE; + } +} + void LLMenuGL::createSpilloverBranch() { if (!mSpilloverBranch) @@ -2348,7 +2540,7 @@ void LLMenuGL::createSpilloverBranch() delete mSpilloverMenu; // technically, you can't tear off spillover menus, but we're passing the handle // along just to be safe - mSpilloverMenu = new LLMenuGL(std::string("More"), std::string("More"), mParentFloaterHandle); + mSpilloverMenu = new LLMenuGL(std::string("More"), std::string("More")); mSpilloverMenu->updateParent(LLMenuGL::sMenuContainer); // Inherit colors mSpilloverMenu->setBackgroundColor( mBackgroundColor ); @@ -2366,22 +2558,12 @@ void LLMenuGL::cleanupSpilloverBranch() // head-recursion to propagate items back up to root menu mSpilloverMenu->cleanupSpilloverBranch(); - removeChild(mSpilloverBranch); - - item_list_t::iterator found_iter = std::find(mItems.begin(), mItems.end(), mSpilloverBranch); - if (found_iter != mItems.end()) - { - mItems.erase(found_iter); - } - // pop off spillover items while (mSpilloverMenu->getItemCount()) { LLMenuItemGL* itemp = mSpilloverMenu->getItem(0); mSpilloverMenu->removeChild(itemp); - mSpilloverMenu->mItems.erase(mSpilloverMenu->mItems.begin()); // put them at the end of our own list - mItems.push_back(itemp); addChild(itemp); } @@ -2495,6 +2677,7 @@ void LLMenuGL::empty( void ) cleanupSpilloverBranch(); mItems.clear(); + mFirstVisibleItem = NULL; deleteAllChildren(); @@ -2504,7 +2687,7 @@ void LLMenuGL::empty( void ) void LLMenuGL::setLeftAndBottom(S32 left, S32 bottom) { setRect(LLRect(left, getRect().mTop, getRect().mRight, bottom)); - arrange(); + needsArrange(); } BOOL LLMenuGL::handleJumpKey(KEY key) @@ -2517,9 +2700,6 @@ BOOL LLMenuGL::handleJumpKey(KEY key) // switch to keyboard navigation mode LLMenuGL::setKeyboardMode(TRUE); - // force highlight to close old menus and any open sub-menus - - //clearHoverItem(); // force highlight to close old menus and open and sub-menus found_it->second->setHighlight(TRUE); found_it->second->doIt(); @@ -2534,40 +2714,18 @@ BOOL LLMenuGL::handleJumpKey(KEY key) // Add the menu item to this menu. BOOL LLMenuGL::append( LLMenuItemGL* item ) { - if (mSpilloverMenu) - { - return mSpilloverMenu->append(item); - } - + if (!item) return FALSE; mItems.push_back( item ); - addChild( item ); - arrange(); - return TRUE; -} - -// *NOTE:Mani - appendNoArrange() should be removed when merging to skinning/viewer2.0 -// Its added as a fix to a viewer 1.23 bug that has already been address by skinning work. -BOOL LLMenuGL::appendNoArrange( LLMenuItemGL* item ) -{ - if (mSpilloverMenu) - { - return mSpilloverMenu->append(item); - } - - mItems.push_back( item ); - addChild( item ); + LLUICtrl::addChild(item); + needsArrange(); return TRUE; } // add a separator to this menu -BOOL LLMenuGL::appendSeparator( const std::string &separator_name ) +BOOL LLMenuGL::addSeparator() { - LLMenuItemGL* separator; - if (separator_name.empty()) - separator = new LLMenuItemSeparatorGL(std::string("separator")); - else - separator = new LLMenuItemSeparatorGL(separator_name); - return append( separator ); + LLMenuItemGL* separator = new LLMenuItemSeparatorGL(); + return addChild(separator); } // add a menu - this will create a cascading menu @@ -2587,35 +2745,10 @@ BOOL LLMenuGL::appendMenu( LLMenuGL* menu ) // Inherit colors menu->setBackgroundColor( mBackgroundColor ); - + menu->updateParent(LLMenuGL::sMenuContainer); return success; } -// Remove a menu item from this menu. -BOOL LLMenuGL::remove( LLMenuItemGL* item ) -{ - if (mSpilloverMenu) - { - cleanupSpilloverBranch(); - } - - item_list_t::iterator found_iter = std::find(mItems.begin(), mItems.end(), item); - if (found_iter != mItems.end()) - { - mItems.erase(found_iter); - } - - removeChild( item ); - - // We keep it around in case someone is pointing at it. - // The caller can delete it if it's safe. - // Note that getMenu() will still not work since its parent isn't a menu. - sMenuContainer->addChild( item ); - - arrange(); - return TRUE; -} - void LLMenuGL::setEnabledSubMenus(BOOL enable) { setEnabled(enable); @@ -2650,6 +2783,7 @@ void LLMenuGL::setItemVisible( const std::string& name, BOOL visible ) if( (*item_iter)->getName() == name ) { (*item_iter)->setVisible( visible ); + needsArrange(); break; } } @@ -2714,6 +2848,7 @@ LLMenuItemGL* LLMenuGL::getHighlightedItem() LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disabled) { + if (mItems.empty()) return NULL; // highlighting first item on a torn off menu is the // same as giving focus to it if (!cur_item && getTornOff()) @@ -2721,14 +2856,8 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa ((LLFloater*)getParent())->setFocus(TRUE); } - item_list_t::iterator cur_item_iter; - for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); ++cur_item_iter) - { - if( (*cur_item_iter) == cur_item) - { - break; - } - } + // Current item position in the items list + item_list_t::iterator cur_item_iter = std::find(mItems.begin(), mItems.end(), cur_item); item_list_t::iterator next_item_iter; if (cur_item_iter == mItems.end()) @@ -2739,6 +2868,10 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa { next_item_iter = cur_item_iter; next_item_iter++; + + // First visible item position in the items list + item_list_t::iterator first_visible_item_iter = std::find(mItems.begin(), mItems.end(), mFirstVisibleItem); + if (next_item_iter == mItems.end()) { next_item_iter = mItems.begin(); @@ -2760,7 +2893,7 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa while(1) { // skip separators and disabled/invisible items - if ((*next_item_iter)->getEnabled() && (*next_item_iter)->getVisible() && (*next_item_iter)->getType() != SEPARATOR_NAME) + if ((*next_item_iter)->getEnabled() && (*next_item_iter)->getVisible() && !dynamic_cast(*next_item_iter)) { if (cur_item) { @@ -2792,6 +2925,8 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disabled) { + if (mItems.empty()) return NULL; + // highlighting first item on a torn off menu is the // same as giving focus to it if (!cur_item && getTornOff()) @@ -2799,14 +2934,8 @@ LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disa ((LLFloater*)getParent())->setFocus(TRUE); } - item_list_t::reverse_iterator cur_item_iter; - for (cur_item_iter = mItems.rbegin(); cur_item_iter != mItems.rend(); ++cur_item_iter) - { - if( (*cur_item_iter) == cur_item) - { - break; - } - } + // Current item reverse position from the end of the list + item_list_t::reverse_iterator cur_item_iter = std::find(mItems.rbegin(), mItems.rend(), cur_item); item_list_t::reverse_iterator prev_item_iter; if (cur_item_iter == mItems.rend()) @@ -2817,6 +2946,10 @@ LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disa { prev_item_iter = cur_item_iter; prev_item_iter++; + + // First visible item reverse position in the items list + item_list_t::reverse_iterator first_visible_item_iter = std::find(mItems.rbegin(), mItems.rend(), mFirstVisibleItem); + if (prev_item_iter == mItems.rend()) { prev_item_iter = mItems.rbegin(); @@ -2826,7 +2959,7 @@ LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disa while(1) { // skip separators and disabled/invisible items - if ((*prev_item_iter)->getEnabled() && (*prev_item_iter)->getVisible() && (*prev_item_iter)->getType() != SEPARATOR_NAME) + if ((*prev_item_iter)->getEnabled() && (*prev_item_iter)->getVisible() && (*prev_item_iter)->getName() != SEPARATOR_NAME) { (*prev_item_iter)->setHighlight(TRUE); return (*prev_item_iter); @@ -2867,17 +3000,15 @@ void LLMenuGL::updateParent(LLView* parentp) { getParent()->removeChild(this); } - parentp->addChild(this); + if (parentp) + { + parentp->addChild(this); + } item_list_t::iterator item_iter; for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) { (*item_iter)->updateBranchParent(parentp); } - - if (mSpilloverMenu) - { - mSpilloverMenu->updateParent(parentp); - } } BOOL LLMenuGL::handleAcceleratorKey(KEY key, MASK mask) @@ -2929,11 +3060,11 @@ BOOL LLMenuGL::handleHover( S32 x, S32 y, MASK mask ) // don't change menu focus unless mouse is moving or alt key is not held down if ((llabs(mMouseVelX) > 0 || - llabs(mMouseVelY) > 0) && + llabs(mMouseVelY) > 0) /*&& (!mHasSelection || - //(mouse_delta_x == 0 && mouse_delta_y == 0) || + (mouse_delta_x == 0 && mouse_delta_y == 0) || (mMouseVelX < 0) || - llabs((F32)mMouseVelY) / llabs((F32)mMouseVelX) > MAX_MOUSE_SLOPE_SUB_MENU)) + llabs((F32)mMouseVelY) / llabs((F32)mMouseVelX) > MAX_MOUSE_SLOPE_SUB_MENU)*/) { for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { @@ -2970,31 +3101,59 @@ BOOL LLMenuGL::handleHover( S32 x, S32 y, MASK mask ) ((LLMenuItemGL*)viewp)->setHighlight(TRUE); LLMenuGL::setKeyboardMode(FALSE); } - mHasSelection = TRUE; + mHasSelection = true; } } } getWindow()->setCursor(UI_CURSOR_ARROW); + + // *HACK Release the mouse capture + // This is done to release the mouse after the Navigation Bar "Back" or "Forward" button + // drop-down menu is shown. Otherwise any other view won't be able to handle mouse events + // until the user chooses one of the drop-down menu items. + return TRUE; } +BOOL LLMenuGL::handleScrollWheel( S32 x, S32 y, S32 clicks ) +{ + return blockMouseEvent(x, y); +} + void LLMenuGL::draw( void ) { + if (mNeedsArrange) + { + arrange(); + mNeedsArrange = FALSE; + } if (mDropShadowed && !mTornOff) { - static LLColor4 color_drop_shadow = LLUI::sColorsGroup->getColor("ColorDropShadow"); static S32 drop_shadow_floater = LLUI::sConfigGroup->getS32("DropShadowFloater"); + static LLColor4 color_drop_shadow = LLUI::sColorsGroup->getColor("ColorDropShadow"); + gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0, - color_drop_shadow, - drop_shadow_floater ); + color_drop_shadow, drop_shadow_floater ); } - LLColor4 bg_color = mBackgroundColor; - if( mBgVisible ) { gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0, mBackgroundColor ); } + + + /*LLRect rootRect = getRootView()->getRect(); + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) + { + LLMenuItemGL* itemp = static_cast(*child_it); + if(itemp) + { + LLRect screenRect; + localRectToScreen(itemp->getRect(),&screenRect); + lldebugs << itemp->getName() << "Visible:" << itemp->getVisible() << " ValidRect: " << itemp->getRect().isValid() << " Overlaps: " << rootRect.overlaps(screenRect) << llendl; + } + }*/ + LLView::draw(); } @@ -3009,8 +3168,10 @@ void LLMenuGL::setVisible(BOOL visible) { if (visible != getVisible()) { + LLView::setVisible(visible); if (!visible) { + lldebugs << "Hiding " << getName() << llendl; mFadeTimer.start(); clearHoverItem(); // reset last known mouse coordinates so @@ -3019,12 +3180,11 @@ void LLMenuGL::setVisible(BOOL visible) mLastMouseY = 0; } else - { - mHasSelection = FALSE; + { + lldebugs << "Showing " << getName() << llendl; + mHasSelection = true; mFadeTimer.stop(); } - - LLView::setVisible(visible); } } @@ -3069,48 +3229,60 @@ void hide_top_view( LLView* view ) } +// x and y are the desired location for the popup, in the spawning_view's +// coordinate frame, NOT necessarily the mouse location // static void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) { - const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect(); + const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size + const S32 CURSOR_WIDTH = 12; + + if(menu->getChildList()->empty()) + { + return; + } + + // Save click point for detecting cursor moves before mouse-up. + // Must be in local coords to compare with mouseUp events. + // If the mouse doesn't move, the menu will stay open ala the Mac. + // See also LLContextMenu::show() + S32 mouse_x, mouse_y; + + // Resetting scrolling position + if (menu->isScrollable() && menu->isScrollPositionOnShowReset()) + { + menu->mFirstVisibleItem = NULL; + } + + menu->setVisible( TRUE ); + + // Fix menu rect if needed. + menu->needsArrange(); + menu->arrangeAndClear(); + + LLUI::getMousePositionLocal(menu->getParent(), &mouse_x, &mouse_y); + LLMenuHolderGL::sContextMenuSpawnPos.set(mouse_x,mouse_y); + + const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getRect(); const S32 HPAD = 2; LLRect rect = menu->getRect(); - //LLView* cur_view = spawning_view; S32 left = x + HPAD; S32 top = y; spawning_view->localPointToOtherView(left, top, &left, &top, menu->getParent()); rect.setLeftTopAndSize( left, top, rect.getWidth(), rect.getHeight() ); - - - //rect.setLeftTopAndSize(x + HPAD, y, rect.getWidth(), rect.getHeight()); menu->setRect( rect ); - S32 bottom; - left = rect.mLeft; - bottom = rect.mBottom; - //menu->getParent()->localPointToScreen( rect.mLeft, rect.mBottom, - // &left, &bottom ); - S32 delta_x = 0; - S32 delta_y = 0; - if( bottom < menu_region_rect.mBottom ) - { - // At this point, we need to move the context menu to the - // other side of the mouse. - //delta_y = menu_region_rect.mBottom - bottom; - delta_y = (rect.getHeight() + 2 * HPAD); - } - if( left > menu_region_rect.mRight - rect.getWidth() ) - { - // At this point, we need to move the context menu to the - // other side of the mouse. - //delta_x = (window_width - rect.getWidth()) - x; - delta_x = -(rect.getWidth() + 2 * HPAD); - } - menu->translate( delta_x, delta_y ); - menu->setVisible( TRUE ); + // Adjust context menu to fit onscreen + LLRect mouse_rect; + const S32 MOUSE_CURSOR_PADDING = 5; + mouse_rect.setLeftTopAndSize(mouse_x - MOUSE_CURSOR_PADDING, + mouse_y + MOUSE_CURSOR_PADDING, + CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2, + CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2); + menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect, FALSE ); menu->getParent()->sendChildToFront(menu); } @@ -3128,6 +3300,12 @@ public: // called to rebuild the draw label virtual void buildDrawLabel( void ); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) + { + LLMenuItemGL::handleMouseUp(x,y,mask); + return TRUE; + } + // doIt() - do the primary funcationality of the menu item. virtual void doIt( void ); @@ -3137,6 +3315,9 @@ protected: LLPieMenu* mBranch; }; +const F32 PIE_MENU_WIDTH = 190; +const F32 PIE_MENU_HEIGHT = 190; + LLPieMenuBranch::LLPieMenuBranch(const std::string& name, const std::string& label, LLPieMenu* branch) @@ -3219,8 +3400,8 @@ LLPieMenu::LLPieMenu(const std::string& name, const std::string& label) mCurRadius(0.f), mRightMouseDown(FALSE) { + setRect(LLRect(0,PIE_MENU_HEIGHT,PIE_MENU_WIDTH,0)); LLMenuGL::setVisible(FALSE); - setCanTearOff(FALSE); } LLPieMenu::LLPieMenu(const std::string& name) @@ -3234,8 +3415,8 @@ LLPieMenu::LLPieMenu(const std::string& name) mCurRadius(0.f), mRightMouseDown(FALSE) { + setRect(LLRect(0,PIE_MENU_HEIGHT,PIE_MENU_WIDTH,0)); LLMenuGL::setVisible(FALSE); - setCanTearOff(FALSE); } @@ -3273,6 +3454,18 @@ void LLPieMenu::initXML(LLXMLNodePtr node, LLView *context, LLUICtrlFactory *fac } } +bool LLPieMenu::addChild(LLView* view, S32 tab_group) +{ + if(LLMenuGL::addChild(view, tab_group)) + { + LLMenuItemSeparatorGL* sep = dynamic_cast(view); + if(sep) + sep->setVisible(false); + return true; + } + return false; +} + // virtual void LLPieMenu::setVisible(BOOL visible) { @@ -3396,7 +3589,7 @@ BOOL LLPieMenu::handleMouseDown( S32 x, S32 y, MASK mask ) } // always handle mouse down as mouse up will close open menus - return handled; + return TRUE; } BOOL LLPieMenu::handleRightMouseDown(S32 x, S32 y, MASK mask) @@ -3637,7 +3830,7 @@ BOOL LLPieMenu::append(LLMenuItemGL *item) } // virtual -BOOL LLPieMenu::appendSeparator(const std::string &separator_name) +BOOL LLPieMenu::addSeparator() { LLMenuItemGL* separator = new LLMenuItemBlankGL(); separator->setFont( LLFontGL::getFontSansSerifSmall() ); @@ -3661,9 +3854,6 @@ BOOL LLPieMenu::appendPieMenu(LLPieMenu *menu) // virtual void LLPieMenu::arrange() { - const S32 rect_height = 190; - const S32 rect_width = 190; - // all divide by 6 const S32 CARD_X = 60; const S32 DIAG_X = 48; @@ -3673,8 +3863,6 @@ void LLPieMenu::arrange() const S32 ITEM_CENTER_X[] = { CARD_X, DIAG_X, 0, -DIAG_X, -CARD_X, -DIAG_X, 0, DIAG_X }; const S32 ITEM_CENTER_Y[] = { 0, DIAG_Y, CARD_Y, DIAG_Y, 0, -DIAG_Y, -CARD_Y, -DIAG_Y }; - LLRect rect; - S32 font_height = 0; if( mItems.size() ) { @@ -3687,8 +3875,7 @@ void LLPieMenu::arrange() // TODO: Compute actual bounding rect for menu - // HACK: casting away const. Should use setRect or some helper function instead. - const_cast(getRect()).setOriginAndSize(getRect().mLeft, getRect().mBottom, rect_width, rect_height ); + LLRect rect = getRect(); // place items around a circle, with item 0 at positive X, // rotating counter-clockwise @@ -3706,7 +3893,7 @@ void LLPieMenu::arrange() item_width, font_height ); // Correct for the actual rectangle size - rect.translate( rect_width/2, rect_height/2 ); + rect.translate( getRect().getWidth()/2, getRect().getHeight()/2 ); item->setRect( rect ); @@ -3760,7 +3947,10 @@ LLMenuItemGL *LLPieMenu::pieItemFromXY(S32 x, S32 y) { if (which == 0) { - return (*item_iter); + if((*item_iter)->getVisible()) + return (*item_iter); + else + return NULL; } which--; } @@ -3804,62 +3994,38 @@ void LLPieMenu::show(S32 x, S32 y, BOOL mouse_down) const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect(); LLView* parent_view = getParent(); - BOOL moved = FALSE; S32 local_x, local_y; parent_view->screenPointToLocal(x, y, &local_x, &local_y); - // HACK: casting away const. Should use setRect or some helper function instead. - const_cast(getRect()).setCenterAndSize(local_x, local_y, width, height); + LLRect rect; + rect.setCenterAndSize(local_x, local_y, width, height); + setRect(rect); + arrange(); // Adjust the pie rectangle to keep it on screen - if (getRect().mLeft < menu_region_rect.mLeft) + if(!menu_region_rect.contains(rect)) { - //mShiftHoriz = menu_region_rect.mLeft - getRect().mLeft; - //getRect().translate( mShiftHoriz, 0 ); - // HACK: casting away const. Should use setRect or some helper function instead. - const_cast(getRect()).translate( menu_region_rect.mLeft - getRect().mLeft, 0 ); - moved = TRUE; - } - - if (getRect().mRight > menu_region_rect.mRight) - { - //mShiftHoriz = menu_region_rect.mRight - getRect().mRight; - //getRect().translate( mShiftHoriz, 0); - // HACK: casting away const. Should use setRect or some helper function instead. - const_cast(getRect()).translate( menu_region_rect.mRight - getRect().mRight, 0 ); - moved = TRUE; - } - - if (getRect().mBottom < menu_region_rect.mBottom) - { - //mShiftVert = menu_region_rect.mBottom - getRect().mBottom; - //getRect().translate( 0, mShiftVert ); - // HACK: casting away const. Should use setRect or some helper function instead. - const_cast(getRect()).translate( 0, menu_region_rect.mBottom - getRect().mBottom ); - moved = TRUE; - } - - - if (getRect().mTop > menu_region_rect.mTop) - { - //mShiftVert = menu_region_rect.mTop - getRect().mTop; - //getRect().translate( 0, mShiftVert ); - // HACK: casting away const. Should use setRect or some helper function instead. - const_cast(getRect()).translate( 0, menu_region_rect.mTop - getRect().mTop ); - moved = TRUE; - } - - // If we had to relocate the pie menu, put the cursor in the - // center of its rectangle - if (moved) - { - LLCoordGL center; - center.mX = (getRect().mLeft + getRect().mRight) / 2; - center.mY = (getRect().mTop + getRect().mBottom) / 2; - - LLUI::setMousePositionLocal(getParent(), center.mX, center.mY); + S32 trans[2]={0,0}; + if (rect.mLeft < menu_region_rect.mLeft) + { + trans[0] = menu_region_rect.mLeft - rect.mLeft; + } + else if (rect.mRight > menu_region_rect.mRight) + { + trans[0] = menu_region_rect.mRight - rect.mRight; + } + if (rect.mBottom < menu_region_rect.mBottom) + { + trans[1] = menu_region_rect.mBottom - rect.mBottom; + } + else if (rect.mTop > menu_region_rect.mTop) + { + trans[1] = menu_region_rect.mTop - rect.mTop; + } + setRect(rect.translate(trans[0],trans[1])); + LLUI::setMousePositionLocal(getParent(),rect.getCenterX(), rect.getCenterY()); } // *FIX: what happens when mouse buttons reversed? @@ -3918,10 +4084,10 @@ void LLPieMenu::hide(BOOL item_selected) static LLRegisterWidget r2("menu_bar"); // Default constructor -LLMenuBarGL::LLMenuBarGL( const std::string& name ) : LLMenuGL ( name, name ) +LLMenuBarGL::LLMenuBarGL( const std::string& name ) +: LLMenuGL ( name, name ) { mHorizontalLayout = TRUE; - setCanTearOff(FALSE); mKeepFixedSize = TRUE; mAltKeyTrigger = FALSE; } @@ -4006,13 +4172,6 @@ LLView* LLMenuBarGL::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory if (child->hasName("menu")) { LLMenuGL *menu = (LLMenuGL*)LLMenuGL::fromXML(child, parent, factory); - // because of lazy initialization, have to disable tear off functionality - // and then re-enable with proper parent handle - if (menu->getCanTearOff()) - { - menu->setCanTearOff(FALSE); - menu->setCanTearOff(TRUE, parent_handle); - } menubar->appendMenu(menu); if (LLMenuGL::sMenuContainer != NULL) { @@ -4052,7 +4211,10 @@ BOOL LLMenuBarGL::handleAcceleratorKey(KEY key, MASK mask) mAltKeyTrigger = FALSE; } - if(!result && (key == KEY_F10 && mask == MASK_CONTROL) && !gKeyboard->getKeyRepeated(key)) + if(!result + && (key == KEY_F10 && mask == MASK_CONTROL) + && !gKeyboard->getKeyRepeated(key) + && isInVisibleChain()) { if (getHighlightedItem()) { @@ -4123,19 +4285,22 @@ BOOL LLMenuBarGL::handleMouseDown(S32 x, S32 y, MASK mask) return LLMenuGL::handleMouseDown(x, y, mask); } -BOOL LLMenuBarGL::handleRightMouseDown(S32 x, S32 y, MASK mask) +void LLMenuBarGL::setVisible(BOOL visible) { - // clicks on menu bar closes existing menus from other contexts but leave - // own menu open so that we get toggle behavior - if (!getHighlightedItem() || !getHighlightedItem()->isActive()) + if(visible != getVisible()) { - LLMenuGL::sMenuContainer->hideMenus(); + if(!visible) + { + lldebugs << "Hiding " << getName() << llendl; + } + else + { + lldebugs << "Showing " << getName() << llendl; + } } - - return LLMenuGL::handleMouseDown(x, y, mask); + LLUICtrl::setVisible(visible); } - void LLMenuBarGL::draw() { LLMenuItemGL* itemp = getHighlightedItem(); @@ -4229,7 +4394,7 @@ S32 LLMenuBarGL::getRightmostMenuEdge() } // add a vertical separator to this menu -BOOL LLMenuBarGL::appendSeparator( const std::string &separator_name ) +BOOL LLMenuBarGL::addSeparator() { LLMenuItemGL* separator = new LLMenuItemVerticalSeparatorGL(); return append( separator ); @@ -4251,6 +4416,8 @@ BOOL LLMenuBarGL::appendMenu( LLMenuGL* menu ) success &= branch->addToAcceleratorList(&mAccelerators); success &= append( branch ); branch->setJumpKey(branch->getJumpKey()); + menu->updateParent(LLMenuGL::sMenuContainer); + return success; } @@ -4327,6 +4494,7 @@ BOOL LLMenuBarGL::handleHover( S32 x, S32 y, MASK mask ) ///============================================================================ /// Class LLMenuHolderGL ///============================================================================ +LLCoordGL LLMenuHolderGL::sContextMenuSpawnPos(S32_MAX, S32_MAX); LLMenuHolderGL::LLMenuHolderGL() : LLPanel(std::string("Menu Holder")) { @@ -4349,7 +4517,7 @@ void LLMenuHolderGL::draw() LLView::draw(); // now draw last selected item as overlay LLMenuItemGL* selecteditem = (LLMenuItemGL*)sItemLastSelectedHandle.get(); - if (selecteditem && sItemActivationTimer.getStarted() && sItemActivationTimer.getElapsedTimeF32() < ACTIVATE_HIGHLIGHT_TIME) + if (selecteditem && selecteditem->getVisible() && sItemActivationTimer.getStarted() && sItemActivationTimer.getElapsedTimeF32() < ACTIVATE_HIGHLIGHT_TIME) { // make sure toggle items, for example, show the proper state when fading out selecteditem->buildDrawLabel(); @@ -4358,10 +4526,10 @@ void LLMenuHolderGL::draw() selecteditem->localRectToOtherView(selecteditem->getLocalRect(), &item_rect, this); F32 interpolant = sItemActivationTimer.getElapsedTimeF32() / ACTIVATE_HIGHLIGHT_TIME; - F32 alpha = lerp(LLMenuItemGL::getHighlightBGColor().mV[VALPHA], 0.f, interpolant); - LLColor4 bg_color(LLMenuItemGL::getHighlightBGColor().mV[VRED], - LLMenuItemGL::getHighlightBGColor().mV[VGREEN], - LLMenuItemGL::getHighlightBGColor().mV[VBLUE], + F32 alpha = lerp(LLMenuItemGL::sHighlightBackground.mV[VALPHA], 0.f, interpolant); + LLColor4 bg_color(LLMenuItemGL::sHighlightBackground.mV[VRED], + LLMenuItemGL::sHighlightBackground.mV[VGREEN], + LLMenuItemGL::sHighlightBackground.mV[VBLUE], alpha); LLUI::pushMatrix(); @@ -4396,6 +4564,68 @@ BOOL LLMenuHolderGL::handleRightMouseDown( S32 x, S32 y, MASK mask ) return handled; } +// This occurs when you mouse-down to spawn a context menu, hold the button +// down, move off the menu, then mouse-up. We want this to close the menu. +BOOL LLMenuHolderGL::handleRightMouseUp( S32 x, S32 y, MASK mask ) +{ + const S32 SLOP = 2; + S32 spawn_dx = (x - sContextMenuSpawnPos.mX); + S32 spawn_dy = (y - sContextMenuSpawnPos.mY); + if (-SLOP <= spawn_dx && spawn_dx <= SLOP + && -SLOP <= spawn_dy && spawn_dy <= SLOP) + { + // we're still inside the slop region from spawning this menu + // so interpret the mouse-up as a single-click to show and leave on + // screen + sContextMenuSpawnPos.set(S32_MAX, S32_MAX); + return TRUE; + } + + BOOL handled = LLView::childrenHandleRightMouseUp(x, y, mask) != NULL; + if (!handled) + { + // clicked off of menu, hide them all + hideMenus(); + } + return handled; +} + +BOOL LLMenuHolderGL::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ + BOOL handled = false; + LLMenuGL* const pMenu = dynamic_cast(getVisibleMenu()); + + if (pMenu) + { + //eat TAB key - EXT-7000 + if (key == KEY_TAB && mask == MASK_NONE) + { + return TRUE; + } + + //handle ESCAPE and RETURN key + handled = LLPanel::handleKey(key, mask, called_from_parent); + if (!handled) + { + if (pMenu->getHighlightedItem()) + { + handled = pMenu->handleKey(key, mask, TRUE); + } + else + { + //highlight first enabled one + if(pMenu->highlightNextItem(NULL)) + { + handled = true; + } + } + } + } + + return handled; + +} + void LLMenuHolderGL::reshape(S32 width, S32 height, BOOL called_from_parent) { if (width != getRect().getWidth() || height != getRect().getHeight()) @@ -4405,17 +4635,17 @@ void LLMenuHolderGL::reshape(S32 width, S32 height, BOOL called_from_parent) LLView::reshape(width, height, called_from_parent); } -BOOL LLMenuHolderGL::hasVisibleMenu() const +LLView* const LLMenuHolderGL::getVisibleMenu() const { for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { LLView* viewp = *child_it; - if (viewp->getVisible() && dynamic_cast(viewp) == NULL) + if (viewp->getVisible() && dynamic_cast(viewp) != NULL && !dynamic_cast(viewp)) { - return TRUE; + return viewp; } } - return FALSE; + return NULL; } @@ -4436,8 +4666,7 @@ BOOL LLMenuHolderGL::hideMenus() for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { LLView* viewp = *child_it; - // clicks off of menu do not hide menu bar - if (dynamic_cast(viewp) == NULL && viewp->getVisible()) + if (dynamic_cast(viewp) != NULL && viewp->getVisible() && !dynamic_cast(viewp)) { viewp->setVisible(FALSE); } @@ -4463,24 +4692,33 @@ void LLMenuHolderGL::setActivatedItem(LLMenuItemGL* item) LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) : LLFloater(menup->getName(), LLRect(0, 100, 100, 0), menup->getLabel(), FALSE, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT, FALSE, FALSE) { + S32 floater_header_size = LLFLOATER_HEADER_SIZE; + + setName(menup->getName()); + setTitle(menup->getLabel()); + setCanMinimize(FALSE); // flag menu as being torn off menup->setTornOff(TRUE); // update menu layout as torn off menu (no spillover menus) - menup->arrange(); + menup->needsArrange(); LLRect rect; menup->localRectToOtherView(LLRect(-1, menup->getRect().getHeight(), menup->getRect().getWidth() + 3, 0), &rect, gFloaterView); // make sure this floater is big enough for menu - mTargetHeight = (F32)(rect.getHeight() + LLFLOATER_HEADER_SIZE + 5); + mTargetHeight = (F32)(rect.getHeight() + floater_header_size); reshape(rect.getWidth(), rect.getHeight()); setRect(rect); // attach menu to floater - menup->setFollowsAll(); + menup->setFollows(FOLLOWS_BOTTOM|FOLLOWS_LEFT); mOldParent = menup->getParent(); addChild(menup); menup->setVisible(TRUE); - menup->translate(-menup->getRect().mLeft + 1, -menup->getRect().mBottom + 1); + + LLRect menu_rect = menup->getRect(); + menu_rect.setOriginAndSize( 1, 1, + menu_rect.getWidth(), menu_rect.getHeight()); + menup->setRect(menu_rect); menup->setDropShadowed(FALSE); mMenu = menup; @@ -4493,19 +4731,13 @@ LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) : void LLTearOffMenu::draw() { mMenu->setBackgroundVisible(isBackgroundOpaque()); - mMenu->arrange(); + mMenu->needsArrange(); if (getRect().getHeight() != mTargetHeight) { // animate towards target height reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), mTargetHeight, LLCriticalDamp::getInterpolant(0.05f)))); } - else - { - // when in stasis, remain big enough to hold menu contents - mTargetHeight = (F32)(mMenu->getRect().getHeight() + LLFLOATER_HEADER_SIZE + 4); - reshape(mMenu->getRect().getWidth() + 3, mMenu->getRect().getHeight() + LLFLOATER_HEADER_SIZE + 5); - } LLFloater::draw(); } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index c4325ac4e..581fcc1a5 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -76,32 +76,40 @@ typedef void (*label_callback)(std::string&,void*); // The LLMenuItemGL represents a single menu item in a menu. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLMenuItemGL : public LLView +class LLMenuItemGL : public LLUICtrl { public: // static functions to control the global color scheme. - static void setEnabledColor( const LLColor4& color ) { sEnabledColor = color; } + /*static void setEnabledColor( const LLColor4& color ) { sEnabledColor = color; } static const LLColor4& getEnabledColor() { return sEnabledColor; } static void setDisabledColor( const LLColor4& color ) { sDisabledColor = color; } static const LLColor4& getDisabledColor() { return sDisabledColor; } static void setHighlightBGColor( const LLColor4& color ) { sHighlightBackground = color; } static const LLColor4& getHighlightBGColor() { return sHighlightBackground; } static void setHighlightFGColor( const LLColor4& color ) { sHighlightForeground = color; } - static const LLColor4& getHighlightFGColor() { return sHighlightForeground; } + static const LLColor4& getHighlightFGColor() { return sHighlightForeground; }*/ LLMenuItemGL( const std::string& name, const std::string& label, KEY key = KEY_NONE, MASK = MASK_NONE ); - virtual ~LLMenuItemGL() {}; + virtual ~LLMenuItemGL(); - virtual void setValue(const LLSD& value) { setLabel(value.asString()); } virtual LLXMLNodePtr getXML(bool save_children = true) const; virtual std::string getType() const { return "item"; } - virtual BOOL handleHover(S32 x, S32 y, MASK mask); + /*virtual*/ void handleVisibilityChange(BOOL new_visibility); + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); + + // LLUICtrl overrides + /*virtual*/ void setValue(const LLSD& value); + /*virtual*/ LLSD getValue() const; virtual BOOL handleAcceleratorKey(KEY key, MASK mask); + LLColor4 getHighlightBgColor() { return mHighlightBackground; } + void setJumpKey(KEY key); KEY getJumpKey() const { return mJumpKey; } @@ -115,8 +123,8 @@ public: virtual U32 getNominalHeight( void ) const; // Marks item as not needing space for check marks or accelerator keys - virtual void setBriefItem(BOOL brief) { mBriefItem = brief; } - virtual BOOL isBriefItem() const { return mBriefItem; } + virtual void setBriefItem(BOOL brief); + virtual BOOL isBriefItem() const; virtual BOOL addToAcceleratorList(std::list *listp); void setAllowKeyRepeat(BOOL allow) { mAllowKeyRepeat = allow; } @@ -128,7 +136,7 @@ public: virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); // Get the parent menu for this item - virtual class LLMenuGL* getMenu(); + virtual class LLMenuGL* getMenu() const; // returns the normal width of this control in pixels - this is // used for calculating the widest item, as well as for horizontal @@ -167,6 +175,7 @@ public: virtual BOOL handleKeyHere( KEY key, MASK mask ); virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); + virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); virtual void draw( void ); BOOL getHover() const { return mGotHover; } @@ -193,13 +202,19 @@ protected: LLUIString mDrawAccelLabel; LLUIString mDrawBranchLabel; + LLColor4 mEnabledColor; + LLColor4 mDisabledColor; + LLColor4 mHighlightBackground; + LLColor4 mHighlightForeground; + BOOL mHighlight; -private: +public: static LLColor4 sEnabledColor; static LLColor4 sDisabledColor; static LLColor4 sHighlightBackground; static LLColor4 sHighlightForeground; +private: // Keyboard and mouse variables BOOL mAllowKeyRepeat; BOOL mGotHover; @@ -216,6 +231,30 @@ private: KEY mJumpKey; }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLMenuItemSeparatorGL +// +// This class represents a separator. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLMenuItemSeparatorGL : public LLMenuItemGL +{ +public: + LLMenuItemSeparatorGL( const std::string &name = std::string() ); + + virtual LLXMLNodePtr getXML(bool save_children = true) const; + + virtual std::string getType() const { return "separator"; } + + // doIt() - do the primary funcationality of the menu item. + virtual void doIt( void ) {} + + virtual void draw( void ); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual BOOL handleHover(S32 x, S32 y, MASK mask); + + virtual U32 getNominalHeight( void ) const; +}; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLMenuItemCallGL @@ -278,6 +317,9 @@ public: void setUserData(void *userdata) { mUserData = userdata; } void* getUserData() const { return mUserData; } +protected: + void updateEnabled( void ); +public: // called to rebuild the draw label virtual void buildDrawLabel( void ); @@ -285,7 +327,8 @@ public: virtual void doIt( void ); virtual BOOL handleAcceleratorKey(KEY key, MASK mask); - + virtual BOOL handleKeyHere(KEY key, MASK mask); + //virtual void draw(); @@ -403,24 +446,35 @@ class LLMenuGL // TODO: The menu and menu item classes share a great deal of functionality and perhaps should be united. // I think it may make the most sense to make LLMenuGL be a subclass of LLMenuItemGL. -MG { +public: + // textual artwork which menugl-imitators may want to match + static const std::string BOOLEAN_TRUE_PREFIX; + static const std::string BRANCH_SUFFIX; + static const std::string ARROW_UP; + static const std::string ARROW_DOWN; + +protected: // let branching menu items use my protected traversal methods friend class LLMenuItemBranchGL; public: - LLMenuGL( const std::string& name, const std::string& label, LLHandle parent_floater = LLHandle()); - LLMenuGL( const std::string& label, LLHandle parent_floater = LLHandle() ); + LLMenuGL( const std::string& name, const std::string& label); + LLMenuGL( const std::string& label); virtual ~LLMenuGL( void ); virtual LLXMLNodePtr getXML(bool save_children = true) const; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); void parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory *factory); - // LLView Functionality - virtual BOOL handleUnicodeCharHere( llwchar uni_char ); - virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - virtual void draw( void ); + /*virtual*/ BOOL handleUnicodeCharHere( llwchar uni_char ); + /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); + /*virtual*/ void draw( void ); virtual void drawBackground(LLMenuItemGL* itemp, LLColor4& color); - virtual void setVisible(BOOL visible); + /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); + /*virtual*/ void removeChild( LLView* ctrl); + /*virtual*/ BOOL postBuild(); virtual BOOL handleAcceleratorKey(KEY key, MASK mask); @@ -437,23 +491,10 @@ public: void setBackgroundColor( const LLColor4& color ) { mBackgroundColor = color; } const LLColor4& getBackgroundColor() const { return mBackgroundColor; } void setBackgroundVisible( BOOL b ) { mBgVisible = b; } - void setCanTearOff(BOOL tear_off, LLHandle parent_floater_handle = LLHandle()); - - // Add the menu item to this menu. - virtual BOOL append( LLMenuItemGL* item ); - - // Remove a menu item from this menu. - virtual BOOL remove( LLMenuItemGL* item ); - - // *NOTE:Mani - appendNoArrange() should be removed when merging to skinning/viewer2.0 - // Its added as a fix to a viewer 1.23 bug that has already been address by skinning work. - virtual BOOL appendNoArrange( LLMenuItemGL* item ); + void setCanTearOff(BOOL tear_off); // add a separator to this menu - virtual BOOL appendSeparator( const std::string &separator_name = LLStringUtil::null ); - - // add a menu - this will create a cascading menu - virtual BOOL appendMenu( LLMenuGL* menu ); + virtual BOOL addSeparator(); // for branching menu items, bring sub menus up to root level of menu hierarchy virtual void updateParent( LLView* parentp ); @@ -477,19 +518,17 @@ public: virtual BOOL isOpen(); + void needsArrange() { mNeedsArrange = TRUE; } // Shape this menu to fit the current state of the children, and // adjust the child rects to fit. This is called automatically // when you add items. *FIX: We may need to deal with visibility // arrangement. virtual void arrange( void ); + void arrangeAndClear( void ); // remove all items on the menu void empty( void ); - // Rearrange the components, and do the right thing if the menu doesn't - // fit in the bounds. - // virtual void arrangeWithBounds(LLRect bounds); - void setItemLastSelected(LLMenuItemGL* item); // must be in menu U32 getItemCount(); // number of menu items LLMenuItemGL* getItem(S32 number); // 0 = first item @@ -510,8 +549,8 @@ public: // Whether to drop shadow menu bar void setDropShadowed( const BOOL shadowed ); - void setParentMenuItem( LLMenuItemGL* parent_menu_item ) { mParentMenuItem = parent_menu_item; } - LLMenuItemGL* getParentMenuItem() const { return mParentMenuItem; } + void setParentMenuItem( LLMenuItemGL* parent_menu_item ) { mParentMenuItem = parent_menu_item->getHandle(); } + LLMenuItemGL* getParentMenuItem() const { return dynamic_cast(mParentMenuItem.get()); } void setTornOff(BOOL torn_off); BOOL getTornOff() { return mTornOff; } @@ -524,15 +563,26 @@ public: static void setKeyboardMode(BOOL mode) { sKeyboardMode = mode; } static BOOL getKeyboardMode() { return sKeyboardMode; } + S32 getShortcutPad() { return mShortcutPad; } + BOOL isScrollable() const { return FALSE; } + static class LLMenuHolderGL* sMenuContainer; + bool isScrollPositionOnShowReset() { return false; } protected: void createSpilloverBranch(); void cleanupSpilloverBranch(); + // Add the menu item to this menu. + virtual BOOL append( LLMenuItemGL* item ); + + // add a menu - this will create a cascading menu + virtual BOOL appendMenu( LLMenuGL* menu ); // TODO: create accessor methods for these? typedef std::list< LLMenuItemGL* > item_list_t; item_list_t mItems; + LLMenuItemGL*mFirstVisibleItem; + typedef std::map navigation_key_map_t; navigation_key_map_t mJumpKeys; S32 mLastMouseX; @@ -541,6 +591,7 @@ protected: S32 mMouseVelY; BOOL mHorizontalLayout; BOOL mKeepFixedSize; + BOOL mNeedsArrange; private: static LLColor4 sDefaultBackgroundColor; @@ -548,17 +599,17 @@ private: LLColor4 mBackgroundColor; BOOL mBgVisible; - LLMenuItemGL* mParentMenuItem; + LLHandle mParentMenuItem; LLUIString mLabel; BOOL mDropShadowed; // Whether to drop shadow - BOOL mHasSelection; + bool mHasSelection; LLFrameTimer mFadeTimer; BOOL mTornOff; class LLMenuItemTearOffGL* mTearOffItem; class LLMenuItemBranchGL* mSpilloverBranch; LLMenuGL* mSpilloverMenu; - LLHandle mParentFloaterHandle; KEY mJumpKey; + S32 mShortcutPad; }; // end class LLMenuGL @@ -604,11 +655,11 @@ public: virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual BOOL isActive() const { return isOpen() && getBranch()->getHighlightedItem(); } + virtual BOOL isActive() const; - virtual BOOL isOpen() const { return getBranch() && getBranch()->isOpen(); } + virtual BOOL isOpen() const; - LLMenuGL *getBranch() const { return (LLMenuGL*)(mBranch.get()); } + LLMenuGL* getBranch() const { return (LLMenuGL*)mBranchHandle.get(); } virtual void updateBranchParent( LLView* parentp ); @@ -624,7 +675,7 @@ public: virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; private: - LLHandle mBranch; + LLHandle mBranchHandle; }; // end class LLMenuItemBranchGL @@ -646,6 +697,9 @@ public: void initXML(LLXMLNodePtr node, LLView *context, LLUICtrlFactory *factory); // LLView Functionality + // hide separators. they are added to 'pad' in empty cells. + virtual bool addChild(LLView* view, S32 tab_group = 0); + // can't set visibility directly, must call show or hide virtual void setVisible(BOOL visible); @@ -657,8 +711,10 @@ public: virtual void draw(); virtual void drawBackground(LLMenuItemGL* itemp, LLColor4& color); +private: virtual BOOL append(LLMenuItemGL* item); - virtual BOOL appendSeparator( const std::string &separator_name = LLStringUtil::null ); +public: + virtual BOOL addSeparator(); BOOL appendPieMenu(LLPieMenu *menu); @@ -703,23 +759,17 @@ public: virtual LLXMLNodePtr getXML(bool save_children = true) const; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - virtual BOOL handleAcceleratorKey(KEY key, MASK mask); - virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual BOOL handleJumpKey(KEY key); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + void setVisible(BOOL visible); + /*virtual*/ BOOL handleAcceleratorKey(KEY key, MASK mask); + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); + /*virtual*/ BOOL handleJumpKey(KEY key); + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); - // rearrange the child rects so they fit the shape of the menu - // bar. - virtual void arrange( void ); - virtual void draw(); - virtual BOOL jumpKeysActive(); + /*virtual*/ void draw(); + /*virtual*/ BOOL jumpKeysActive(); // add a vertical separator to this menu - virtual BOOL appendSeparator( const std::string &separator_name = LLStringUtil::null ); - - // add a menu - this will create a drop down menu. - virtual BOOL appendMenu( LLMenuGL* menu ); + virtual BOOL addSeparator(); // LLView Functionality virtual BOOL handleHover( S32 x, S32 y, MASK mask ); @@ -730,6 +780,12 @@ public: void resetMenuTrigger() { mAltKeyTrigger = FALSE; } private: + // add a menu - this will create a drop down menu. + virtual BOOL appendMenu( LLMenuGL* menu ); + // rearrange the child rects so they fit the shape of the menu + // bar. + virtual void arrange( void ); + void checkMenuTrigger(); std::list mAccelerators; @@ -757,11 +813,20 @@ public: virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + // Close context menus on right mouse up not handled by menus. + /*virtual*/ BOOL handleRightMouseUp( S32 x, S32 y, MASK mask ); + + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); virtual const LLRect getMenuRect() const { return getLocalRect(); } - virtual BOOL hasVisibleMenu() const; + LLView*const getVisibleMenu() const; + virtual BOOL hasVisibleMenu() const {return getVisibleMenu() != NULL;} static void setActivatedItem(LLMenuItemGL* item); + // Need to detect if mouse-up after context menu spawn has moved. + // If not, need to keep the menu up. + static LLCoordGL sContextMenuSpawnPos; + private: static LLHandle sItemLastSelectedHandle; static LLFrameTimer sItemActivationTimer; @@ -805,7 +870,7 @@ private: class LLMenuItemTearOffGL : public LLMenuItemGL { public: - LLMenuItemTearOffGL( LLHandle parent_floater_handle = LLHandle()); + LLMenuItemTearOffGL(); virtual LLXMLNodePtr getXML(bool save_children = true) const; virtual std::string getType() const { return "tearoff_menu"; } @@ -814,8 +879,7 @@ public: virtual void draw(void); virtual U32 getNominalHeight() const; -private: - LLHandle mParentHandle; + LLFloater* getParentFloater(); }; diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index 29ea32816..377c9a12b 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -280,7 +280,7 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, } //add the panel, add it to proper maps - mTabContainer->addTabPanel(floaterp, floaterp->getShortTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point); + mTabContainer->addTabPanel(floaterp, floaterp->getShortTitle(), FALSE, 0, FALSE, insertion_point); mFloaterDataMap[floaterp->getHandle()] = floater_data; updateResizeLimits(); @@ -366,10 +366,10 @@ void LLMultiFloater::removeFloater(LLFloater* floaterp) updateResizeLimits(); - tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false); + tabOpen((LLFloater*)mTabContainer->getCurrentPanel()); } -void LLMultiFloater::tabOpen(LLFloater* opened_floater, bool from_click) +void LLMultiFloater::tabOpen(LLFloater* opened_floater) { // default implementation does nothing } @@ -464,12 +464,9 @@ void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing) mTabContainer->setTabPanelFlashing(floaterp, flashing); } -//static -void LLMultiFloater::onTabSelected(void* userdata, bool from_click) +void LLMultiFloater::onTabSelected() { - LLMultiFloater* floaterp = (LLMultiFloater*)userdata; - - floaterp->tabOpen((LLFloater*)floaterp->mTabContainer->getCurrentPanel(), from_click); + tabOpen((LLFloater*)mTabContainer->getCurrentPanel()); } void LLMultiFloater::setCanResize(BOOL can_resize) @@ -499,6 +496,7 @@ BOOL LLMultiFloater::postBuild() if (checkRequirements()) { mTabContainer = getChild("Preview Tabs"); + mTabContainer->setCommitCallback(boost::bind(&LLMultiFloater::onTabSelected, this)); return TRUE; } diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index 29c03b3c4..0ac9ee856 100644 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -60,7 +60,7 @@ public: virtual void showFloater(LLFloater* floaterp); virtual void removeFloater(LLFloater* floaterp); - virtual void tabOpen(LLFloater* opened_floater, bool from_click); + virtual void tabOpen(LLFloater* opened_floater); virtual void tabClose(); virtual BOOL selectFloater(LLFloater* floaterp); @@ -74,7 +74,7 @@ public: virtual void setFloaterFlashing(LLFloater* floaterp, BOOL flashing); virtual BOOL closeAllFloaters(); //Returns FALSE if the floater could not be closed due to pending confirmation dialogs void setTabContainer(LLTabContainer* tab_container) { if (!mTabContainer) mTabContainer = tab_container; } - static void onTabSelected(void* userdata, bool); + void onTabSelected(); virtual void updateResizeLimits(); diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp index b8ebb3d6b..c3a0f5a6b 100644 --- a/indra/llui/llmultisliderctrl.cpp +++ b/indra/llui/llmultisliderctrl.cpp @@ -127,7 +127,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const std::string& name, const LLRect& rect &LLLineEditor::prevalidateFloat ); mEditor->setFollowsLeft(); mEditor->setFollowsBottom(); - mEditor->setFocusReceivedCallback( &LLMultiSliderCtrl::onEditorGainFocus, this ); + mEditor->setFocusReceivedCallback( boost::bind(&LLMultiSliderCtrl::onFocusReceived, this) ); mEditor->setIgnoreTab(TRUE); // don't do this, as selecting the entire text is single clicking in some cases // and double clicking in others @@ -151,16 +151,6 @@ LLMultiSliderCtrl::~LLMultiSliderCtrl() // Children all cleaned up by default view destructor. } -// static -void LLMultiSliderCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata ) -{ - LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata; - llassert( caller == self->mEditor ); - - self->onFocusReceived(); -} - - void LLMultiSliderCtrl::setValue(const LLSD& value) { mMultiSlider->setValue(value); diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h index 47b1d1fb1..05e15178c 100644 --- a/indra/llui/llmultisliderctrl.h +++ b/indra/llui/llmultisliderctrl.h @@ -126,7 +126,6 @@ public: static void onSliderCommit(LLUICtrl* caller, void* userdata); static void onEditorCommit(LLUICtrl* ctrl, void* userdata); - static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); private: diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index dc0cf9c87..89b43f212 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -731,6 +731,13 @@ std::string LLNotification::getLabel() const return label; } +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a +bool LLNotification::hasLabel() const +{ + return !mTemplatep->mLabel.empty(); +} +// [/SL:KB] + std::string LLNotification::getURL() const { if (!mTemplatep) diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index aac44ddf1..b6ee760f3 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -385,6 +385,10 @@ public: return mTimestamp; } +// [SL:KB] - Patch: UI-Notifications | Checked: 2011-04-11 (Catznip-2.5.0a) | Added: Catznip-2.5.0a + bool hasLabel() const; +// [/SL:KB] + std::string getType() const; std::string getMessage() const; std::string getLabel() const; diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 9dc217e21..136dcf524 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -79,7 +79,6 @@ void LLPanel::init() mBorder = NULL; mDefaultBtn = NULL; setIsChrome(FALSE); //is this a decorator to a live window or a form? - mLastTabGroup = 0; mPanelHandle.bind(this); setTabStop(FALSE); @@ -269,20 +268,6 @@ void LLPanel::setDefaultBtn(const std::string& id) } } -void LLPanel::addCtrl( LLUICtrl* ctrl, S32 tab_group) -{ - mLastTabGroup = tab_group; - - LLView::addCtrl(ctrl, tab_group); -} - -void LLPanel::addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group) -{ - mLastTabGroup = tab_group; - - LLView::addCtrlAtEnd(ctrl, tab_group); -} - BOOL LLPanel::handleKeyHere( KEY key, MASK mask ) { BOOL handled = FALSE; @@ -491,7 +476,18 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *fac } else { - panelp->initPanelXML(node, parent, factory); + if(!factory->builtPanel(panelp)) + panelp->initPanelXML(node, parent, factory); + else + { + LLRect new_rect = panelp->getRect(); + // override rectangle with embedding parameters as provided + panelp->createRect(node, new_rect, parent); + panelp->setOrigin(new_rect.mLeft, new_rect.mBottom); + panelp->setShape(new_rect); + // optionally override follows flags from including nodes + panelp->parseFollowsFlags(node); + } } return panelp; @@ -760,16 +756,6 @@ BOOL LLPanel::childHasFocus(const std::string& id) } } - -void LLPanel::childSetFocusChangedCallback(const std::string& id, void (*cb)(LLFocusableElement*, void*), void* user_data) -{ - LLUICtrl* child = getChild(id, true); - if (child) - { - child->setFocusChangedCallback(cb, user_data); - } -} - void LLPanel::childSetCommitCallback(const std::string& id, void (*cb)(LLUICtrl*, void*), void *userdata ) { LLUICtrl* child = getChild(id, true); @@ -945,24 +931,6 @@ LLPanel *LLPanel::childGetVisibleTab(const std::string& id) const return NULL; } -void LLPanel::childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata, void (*on_precommit)(void*,bool)) -{ - LLTabContainer* child = getChild(id); - if (child) - { - LLPanel *panel = child->getPanelByName(tabname); - if (panel) - { - child->setTabChangeCallback(panel, on_tab_clicked); - child->setTabUserData(panel, userdata); - if (on_precommit) - { - child->setTabPrecommitChangeCallback(panel, on_precommit); - } - } - } -} - void LLPanel::childSetKeystrokeCallback(const std::string& id, void (*keystroke_callback)(LLLineEditor* caller, void* user_data), void *user_data) { LLLineEditor* child = getChild(id); @@ -1199,9 +1167,13 @@ void LLLayoutStack::draw() } } -void LLLayoutStack::removeCtrl(LLUICtrl* ctrl) +void LLLayoutStack::removeChild(LLView* ctrl) { - LLEmbeddedPanel* embedded_panelp = findEmbeddedPanel((LLPanel*)ctrl); + LLView::removeChild(ctrl); + LLPanel* panel = dynamic_cast(ctrl); + if(!panel) + return; + LLEmbeddedPanel* embedded_panelp = findEmbeddedPanel(panel); if (embedded_panelp) { @@ -1210,10 +1182,8 @@ void LLLayoutStack::removeCtrl(LLUICtrl* ctrl) } // need to update resizebars - + calcMinExtents(); - - LLView::removeCtrl(ctrl); } LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index f6373f71c..ad721cbf5 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -138,8 +138,6 @@ public: LLHandle getHandle() const { return mPanelHandle; } - S32 getLastTabGroup() const { return mLastTabGroup; } - const LLCallbackMap::map_t& getFactoryMap() const { return mFactoryMap; } BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); @@ -170,7 +168,6 @@ public: // LLUICtrl void childSetFocus(const std::string& id, BOOL focus = TRUE); BOOL childHasFocus(const std::string& id); - void childSetFocusChangedCallback(const std::string& id, void (*cb)(LLFocusableElement*, void*), void* user_data = NULL); void childSetCommitCallback(const std::string& id, void (*cb)(LLUICtrl*, void*), void* userdata = NULL ); void childSetDoubleClickCallback(const std::string& id, void (*cb)(void*), void* userdata = NULL ); @@ -201,7 +198,6 @@ public: // LLTabContainer void childShowTab(const std::string& id, const std::string& tabname, bool visible = true); LLPanel *childGetVisibleTab(const std::string& id) const; - void childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata, void (*on_precommit)(void*,bool) = NULL); // LLTextBox void childSetWrappedText(const std::string& id, const std::string& text, bool visible = true); @@ -236,10 +232,6 @@ private: // common construction logic void init(); - // From LLView - virtual void addCtrl( LLUICtrl* ctrl, S32 tab_group ); - virtual void addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group); - // Unified error reporting for the child* functions typedef std::set expected_members_list_t; mutable expected_members_list_t mExpectedMembers; @@ -254,7 +246,6 @@ private: LLViewBorder* mBorder; LLButton* mDefaultBtn; std::string mLabel; - S32 mLastTabGroup; LLRootHandle mPanelHandle; typedef std::map ui_string_map_t; @@ -279,7 +270,7 @@ public: /*virtual*/ void draw(); /*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const; - /*virtual*/ void removeCtrl(LLUICtrl* ctrl); + /*virtual*/ void removeChild(LLView* ctrl); static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp index 46b73f281..a0a9b36b9 100644 --- a/indra/llui/llresizebar.cpp +++ b/indra/llui/llresizebar.cpp @@ -185,7 +185,8 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask) if (mSnappingEnabled) { - static LLCachedControl snap_margin (*LLUI::sConfigGroup,"SnapMargin", 0); + //static LLCachedControl snap_margin (*LLUI::sConfigGroup,"SnapMargin", 0); + S32 snap_margin = LLUI::sConfigGroup->getS32("SnapMargin"); switch( mSide ) { case LEFT: diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp index 1d25f3701..690f12b42 100644 --- a/indra/llui/llresizehandle.cpp +++ b/indra/llui/llresizehandle.cpp @@ -46,7 +46,7 @@ const S32 RESIZE_BORDER_WIDTH = 3; LLResizeHandle::LLResizeHandle( const std::string& name, const LLRect& rect, S32 min_width, S32 min_height, ECorner corner ) : - LLView( name, rect, TRUE ), + LLView( name, rect, FALSE ), mDragLastScreenX( 0 ), mDragLastScreenY( 0 ), mLastMouseScreenX( 0 ), @@ -205,7 +205,8 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask) LLView* snap_view = NULL; LLView* test_view = NULL; - static LLCachedControl snap_margin (*LLUI::sConfigGroup,"SnapMargin", 0); + //static LLCachedControl snap_margin (*LLUI::sConfigGroup,"SnapMargin", 0); + S32 snap_margin = LLUI::sConfigGroup->getS32("SnapMargin"); // now do snapping switch(mCorner) { diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index 825a411c4..d41606636 100644 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -73,7 +73,8 @@ LLScrollbar::LLScrollbar( mHighlightColor ( LLUI::sColorsGroup->getColor("DefaultHighlightLight") ), mShadowColor ( LLUI::sColorsGroup->getColor("DefaultShadowLight") ), mOnScrollEndCallback( NULL ), - mOnScrollEndData( NULL ) + mOnScrollEndData( NULL ), + mThickness( SCROLLBAR_SIZE ) { //llassert( 0 <= mDocSize ); //llassert( 0 <= mDocPos && mDocPos <= mDocSize ); @@ -92,22 +93,22 @@ LLScrollbar::LLScrollbar( if( LLScrollbar::VERTICAL == mOrientation ) { - line_up_rect.setLeftTopAndSize( 0, getRect().getHeight(), SCROLLBAR_SIZE, SCROLLBAR_SIZE ); + line_up_rect.setLeftTopAndSize( 0, getRect().getHeight(), mThickness, mThickness ); line_up_img="UIImgBtnScrollUpOutUUID"; line_up_selected_img="UIImgBtnScrollUpInUUID"; - line_down_rect.setOriginAndSize( 0, 0, SCROLLBAR_SIZE, SCROLLBAR_SIZE ); + line_down_rect.setOriginAndSize( 0, 0, mThickness, mThickness ); line_down_img="UIImgBtnScrollDownOutUUID"; line_down_selected_img="UIImgBtnScrollDownInUUID"; } else { // Horizontal - line_up_rect.setOriginAndSize( 0, 0, SCROLLBAR_SIZE, SCROLLBAR_SIZE ); + line_up_rect.setOriginAndSize( 0, 0, mThickness, mThickness ); line_up_img="UIImgBtnScrollLeftOutUUID"; line_up_selected_img="UIImgBtnScrollLeftInUUID"; - line_down_rect.setOriginAndSize( getRect().getWidth() - SCROLLBAR_SIZE, 0, SCROLLBAR_SIZE, SCROLLBAR_SIZE ); + line_down_rect.setOriginAndSize( getRect().getWidth() - mThickness, 0, mThickness, mThickness ); line_down_img="UIImgBtnScrollRightOutUUID"; line_down_selected_img="UIImgBtnScrollRightInUUID"; } @@ -126,7 +127,7 @@ LLScrollbar::LLScrollbar( line_up_btn->setFollowsLeft(); line_up_btn->setFollowsBottom(); } - line_up_btn->setHeldDownCallback( &LLScrollbar::onLineUpBtnPressed ); + line_up_btn->setHeldDownCallback( boost::bind(&LLScrollbar::onLineUpBtnPressed, (void*)this) ); line_up_btn->setTabStop(FALSE); line_up_btn->setScaleImage(TRUE); @@ -137,7 +138,7 @@ LLScrollbar::LLScrollbar( &LLScrollbar::onLineDownBtnPressed, this, LLFontGL::getFontSansSerif() ); line_down_btn->setFollowsRight(); line_down_btn->setFollowsBottom(); - line_down_btn->setHeldDownCallback( &LLScrollbar::onLineDownBtnPressed ); + line_down_btn->setHeldDownCallback( boost::bind(&LLScrollbar::onLineDownBtnPressed, this) ); line_down_btn->setTabStop(FALSE); line_down_btn->setScaleImage(TRUE); addChild(line_down_btn); @@ -158,7 +159,8 @@ void LLScrollbar::setDocParams( S32 size, S32 pos ) updateThumbRect(); } -void LLScrollbar::setDocPos(S32 pos, BOOL update_thumb) +// returns true if document position really changed +bool LLScrollbar::setDocPos(S32 pos, BOOL update_thumb) { pos = llclamp(pos, 0, getDocPosMax()); if (pos != mDocPos) @@ -175,7 +177,9 @@ void LLScrollbar::setDocPos(S32 pos, BOOL update_thumb) { updateThumbRect(); } + return true; } + return false; } void LLScrollbar::setDocSize(S32 size) @@ -221,7 +225,7 @@ void LLScrollbar::updateThumbRect() const S32 THUMB_MIN_LENGTH = 16; S32 window_length = (mOrientation == LLScrollbar::HORIZONTAL) ? getRect().getWidth() : getRect().getHeight(); - S32 thumb_bg_length = llmax(0, window_length - 2 * SCROLLBAR_SIZE); + S32 thumb_bg_length = llmax(0, window_length - 2 * mThickness); S32 visible_lines = llmin( mDocSize, mPageSize ); S32 thumb_length = mDocSize ? llmin(llmax( visible_lines * thumb_bg_length / mDocSize, THUMB_MIN_LENGTH), thumb_bg_length) : thumb_bg_length; @@ -229,24 +233,24 @@ void LLScrollbar::updateThumbRect() if( mOrientation == LLScrollbar::VERTICAL ) { - S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE; - S32 thumb_start_min = SCROLLBAR_SIZE + THUMB_MIN_LENGTH; + S32 thumb_start_max = thumb_bg_length + mThickness; + S32 thumb_start_min = mThickness + THUMB_MIN_LENGTH; S32 thumb_start = variable_lines ? llmin( llmax(thumb_start_max - (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min), thumb_start_max ) : thumb_start_max; mThumbRect.mLeft = 0; mThumbRect.mTop = thumb_start; - mThumbRect.mRight = SCROLLBAR_SIZE; + mThumbRect.mRight = mThickness; mThumbRect.mBottom = thumb_start - thumb_length; } else { // Horizontal - S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE - thumb_length; - S32 thumb_start_min = SCROLLBAR_SIZE; + S32 thumb_start_max = thumb_bg_length + mThickness - thumb_length; + S32 thumb_start_min = mThickness; S32 thumb_start = variable_lines ? llmin(llmax( thumb_start_min + (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min), thumb_start_max ) : thumb_start_min; mThumbRect.mLeft = thumb_start; - mThumbRect.mTop = SCROLLBAR_SIZE; + mThumbRect.mTop = mThickness; mThumbRect.mRight = thumb_start + thumb_length; mThumbRect.mBottom = 0; } @@ -318,21 +322,21 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) // S32 old_pos = mThumbRect.mTop; S32 delta_pixels = y - mDragStartY; - if( mOrigRect.mBottom + delta_pixels < SCROLLBAR_SIZE ) + if( mOrigRect.mBottom + delta_pixels < mThickness ) { - delta_pixels = SCROLLBAR_SIZE - mOrigRect.mBottom - 1; + delta_pixels = mThickness - mOrigRect.mBottom - 1; } else - if( mOrigRect.mTop + delta_pixels > height - SCROLLBAR_SIZE ) + if( mOrigRect.mTop + delta_pixels > height - mThickness ) { - delta_pixels = height - SCROLLBAR_SIZE - mOrigRect.mTop + 1; + delta_pixels = height - mThickness - mOrigRect.mTop + 1; } mThumbRect.mTop = mOrigRect.mTop + delta_pixels; mThumbRect.mBottom = mOrigRect.mBottom + delta_pixels; S32 thumb_length = mThumbRect.getHeight(); - S32 thumb_track_length = height - 2 * SCROLLBAR_SIZE; + S32 thumb_track_length = height - 2 * mThickness; if( delta_pixels != mLastDelta || mDocChanged) @@ -343,7 +347,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) { S32 variable_lines = getDocPosMax(); S32 pos = mThumbRect.mTop; - F32 ratio = F32(pos - SCROLLBAR_SIZE - thumb_length) / usable_track_length; + F32 ratio = F32(pos - mThickness - thumb_length) / usable_track_length; S32 new_pos = llclamp( S32(variable_lines - ratio * variable_lines + 0.5f), 0, variable_lines ); // Note: we do not call updateThumbRect() here. Instead we let the thumb and the document go slightly @@ -362,21 +366,21 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) S32 delta_pixels = x - mDragStartX; - if( mOrigRect.mLeft + delta_pixels < SCROLLBAR_SIZE ) + if( mOrigRect.mLeft + delta_pixels < mThickness ) { - delta_pixels = SCROLLBAR_SIZE - mOrigRect.mLeft - 1; + delta_pixels = mThickness - mOrigRect.mLeft - 1; } else - if( mOrigRect.mRight + delta_pixels > width - SCROLLBAR_SIZE ) + if( mOrigRect.mRight + delta_pixels > width - mThickness ) { - delta_pixels = width - SCROLLBAR_SIZE - mOrigRect.mRight + 1; + delta_pixels = width - mThickness - mOrigRect.mRight + 1; } mThumbRect.mLeft = mOrigRect.mLeft + delta_pixels; mThumbRect.mRight = mOrigRect.mRight + delta_pixels; S32 thumb_length = mThumbRect.getWidth(); - S32 thumb_track_length = width - 2 * SCROLLBAR_SIZE; + S32 thumb_track_length = width - 2 * mThickness; if( delta_pixels != mLastDelta || mDocChanged) { @@ -386,7 +390,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) { S32 variable_lines = getDocPosMax(); S32 pos = mThumbRect.mLeft; - F32 ratio = F32(pos - SCROLLBAR_SIZE) / usable_track_length; + F32 ratio = F32(pos - mThickness) / usable_track_length; S32 new_pos = llclamp( S32(ratio * variable_lines + 0.5f), 0, variable_lines); @@ -405,7 +409,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) } else { - handled = childrenHandleMouseUp( x, y, mask ) != NULL; + handled = childrenHandleHover( x, y, mask ) != NULL; } // Opaque @@ -423,8 +427,8 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) BOOL LLScrollbar::handleScrollWheel(S32 x, S32 y, S32 clicks) { - changeLine( clicks * mStepSize, TRUE ); - return TRUE; + BOOL handled = changeLine( clicks * mStepSize, TRUE ); + return handled; } BOOL LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, @@ -475,14 +479,14 @@ void LLScrollbar::reshape(S32 width, S32 height, BOOL called_from_parent) if (mOrientation == VERTICAL) { - up_button->reshape(up_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, SCROLLBAR_SIZE)); - down_button->reshape(down_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, SCROLLBAR_SIZE)); + up_button->reshape(up_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, mThickness)); + down_button->reshape(down_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, mThickness)); up_button->setOrigin(up_button->getRect().mLeft, getRect().getHeight() - up_button->getRect().getHeight()); } else { - up_button->reshape(llmin(getRect().getWidth() / 2, SCROLLBAR_SIZE), up_button->getRect().getHeight()); - down_button->reshape(llmin(getRect().getWidth() / 2, SCROLLBAR_SIZE), down_button->getRect().getHeight()); + up_button->reshape(llmin(getRect().getWidth() / 2, mThickness), up_button->getRect().getHeight()); + down_button->reshape(llmin(getRect().getWidth() / 2, mThickness), down_button->getRect().getHeight()); down_button->setOrigin(getRect().getWidth() - down_button->getRect().getWidth(), down_button->getRect().mBottom); } updateThumbRect(); @@ -513,10 +517,10 @@ void LLScrollbar::draw() if (!rounded_rect_imagep) { - gl_rect_2d(mOrientation == HORIZONTAL ? SCROLLBAR_SIZE : 0, - mOrientation == VERTICAL ? getRect().getHeight() - 2 * SCROLLBAR_SIZE : getRect().getHeight(), - mOrientation == HORIZONTAL ? getRect().getWidth() - 2 * SCROLLBAR_SIZE : getRect().getWidth(), - mOrientation == VERTICAL ? SCROLLBAR_SIZE : 0, mTrackColor, TRUE); + gl_rect_2d(mOrientation == HORIZONTAL ? mThickness : 0, + mOrientation == VERTICAL ? getRect().getHeight() - 2 * mThickness : getRect().getHeight(), + mOrientation == HORIZONTAL ? getRect().getWidth() - 2 * mThickness : getRect().getWidth(), + mOrientation == VERTICAL ? mThickness : 0, mTrackColor, TRUE); gl_rect_2d(mThumbRect, mThumbColor, TRUE); @@ -560,9 +564,9 @@ void LLScrollbar::draw() } // end draw -void LLScrollbar::changeLine( S32 delta, BOOL update_thumb ) +bool LLScrollbar::changeLine( S32 delta, BOOL update_thumb ) { - setDocPos(mDocPos + delta, update_thumb); + return setDocPos(mDocPos + delta, update_thumb); } void LLScrollbar::setValue(const LLSD& value) diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h index 0bbf8662a..da13ff2af 100644 --- a/indra/llui/llscrollbar.h +++ b/indra/llui/llscrollbar.h @@ -82,7 +82,7 @@ public: // How many "lines" the "document" has scrolled. // 0 <= DocPos <= DocSize - DocVisibile - void setDocPos( S32 pos, BOOL update_thumb = TRUE ); + bool setDocPos( S32 pos, BOOL update_thumb = TRUE ); S32 getDocPos() const { return mDocPos; } BOOL isAtBeginning(); @@ -113,7 +113,7 @@ public: private: void updateThumbRect(); - void changeLine(S32 delta, BOOL update_thumb ); + bool changeLine(S32 delta, BOOL update_thumb ); void (*mChangeCallback)( S32 new_pos, LLScrollbar* self, void* userdata ); void* mCallbackUserData; @@ -142,6 +142,7 @@ private: void (*mOnScrollEndCallback)(void*); void *mOnScrollEndData; + S32 mThickness; }; diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 28890b199..8e740384a 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -69,52 +69,31 @@ LLScrollableContainerView::LLScrollableContainerView( const std::string& name, BOOL is_opaque, const LLColor4& bg_color ) : LLUICtrl( name, rect, FALSE, NULL, NULL ), - mScrolledView( scrolled_view ), - mIsOpaque( is_opaque ), - mBackgroundColor( bg_color ), - mReserveScrollCorner( FALSE ), mAutoScrolling( FALSE ), - mAutoScrollRate( 0.f ) + mAutoScrollRate( 0.f ), + mBackgroundColor( bg_color ), + mIsOpaque( is_opaque ), + mHideScrollbar( FALSE ), + mReserveScrollCorner( FALSE ), + mMinAutoScrollRate( MIN_AUTO_SCROLL_RATE ), + mMaxAutoScrollRate( MAX_AUTO_SCROLL_RATE ), + mScrolledView( scrolled_view ) { if( mScrolledView ) { - addChild( mScrolledView ); + LLView::addChild( mScrolledView ); } - init(); -} - -// LLUICtrl constructor -LLScrollableContainerView::LLScrollableContainerView( const std::string& name, const LLRect& rect, - LLUICtrl* scrolled_ctrl, BOOL is_opaque, - const LLColor4& bg_color) : - LLUICtrl( name, rect, FALSE, NULL, NULL ), - mScrolledView( scrolled_ctrl ), - mIsOpaque( is_opaque ), - mBackgroundColor( bg_color ), - mReserveScrollCorner( FALSE ), - mAutoScrolling( FALSE ), - mAutoScrollRate( 0.f ) -{ - if( scrolled_ctrl ) - { - addChild( scrolled_ctrl ); - } - - init(); -} - -void LLScrollableContainerView::init() -{ + S32 scrollbar_size = SCROLLBAR_SIZE; LLRect border_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 ); mBorder = new LLViewBorder( std::string("scroll border"), border_rect, LLViewBorder::BEVEL_IN ); - addChild( mBorder ); + LLView::addChild( mBorder ); mInnerRect.set( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - mInnerRect.stretch( -mBorder->getBorderWidth() ); + mInnerRect.stretch( -getBorderWidth() ); LLRect vertical_scroll_rect = mInnerRect; - vertical_scroll_rect.mLeft = vertical_scroll_rect.mRight - SCROLLBAR_SIZE; + vertical_scroll_rect.mLeft = vertical_scroll_rect.mRight - scrollbar_size; mScrollbar[VERTICAL] = new LLScrollbar( std::string("scrollable vertical"), vertical_scroll_rect, LLScrollbar::VERTICAL, @@ -123,14 +102,14 @@ void LLScrollableContainerView::init() mInnerRect.getHeight(), NULL, this, VERTICAL_MULTIPLE); - addChild( mScrollbar[VERTICAL] ); + LLView::addChild( mScrollbar[VERTICAL] ); mScrollbar[VERTICAL]->setVisible( FALSE ); mScrollbar[VERTICAL]->setFollowsRight(); mScrollbar[VERTICAL]->setFollowsTop(); mScrollbar[VERTICAL]->setFollowsBottom(); LLRect horizontal_scroll_rect = mInnerRect; - horizontal_scroll_rect.mTop = horizontal_scroll_rect.mBottom + SCROLLBAR_SIZE; + horizontal_scroll_rect.mTop = horizontal_scroll_rect.mBottom + scrollbar_size; mScrollbar[HORIZONTAL] = new LLScrollbar( std::string("scrollable horizontal"), horizontal_scroll_rect, LLScrollbar::HORIZONTAL, @@ -139,7 +118,7 @@ void LLScrollableContainerView::init() mInnerRect.getWidth(), NULL, this, HORIZONTAL_MULTIPLE); - addChild( mScrollbar[HORIZONTAL] ); + LLView::addChild( mScrollbar[HORIZONTAL] ); mScrollbar[HORIZONTAL]->setVisible( FALSE ); mScrollbar[HORIZONTAL]->setFollowsLeft(); mScrollbar[HORIZONTAL]->setFollowsRight(); @@ -190,8 +169,8 @@ void LLScrollableContainerView::reshape(S32 width, S32 height, { LLUICtrl::reshape( width, height, called_from_parent ); - mInnerRect.set( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - mInnerRect.stretch( -mBorder->getBorderWidth() ); + mInnerRect = getLocalRect(); + mInnerRect.stretch( -getBorderWidth() ); if (mScrolledView) { @@ -201,22 +180,33 @@ void LLScrollableContainerView::reshape(S32 width, S32 height, S32 visible_height = 0; BOOL show_v_scrollbar = FALSE; BOOL show_h_scrollbar = FALSE; - calcVisibleSize( scrolled_rect, &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); + calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); mScrollbar[VERTICAL]->setDocSize( scrolled_rect.getHeight() ); mScrollbar[VERTICAL]->setPageSize( visible_height ); mScrollbar[HORIZONTAL]->setDocSize( scrolled_rect.getWidth() ); mScrollbar[HORIZONTAL]->setPageSize( visible_width ); + updateScroll(); } } BOOL LLScrollableContainerView::handleKeyHere(KEY key, MASK mask) { + // allow scrolled view to handle keystrokes in case it delegated keyboard focus + // to the scroll container. + // NOTE: this should not recurse indefinitely as handleKeyHere + // should not propagate to parent controls, so mScrolledView should *not* + // call LLScrollContainer::handleKeyHere in turn + if (mScrolledView && mScrolledView->handleKeyHere(key, mask)) + { + return TRUE; + } for( S32 i = 0; i < SCROLLBAR_COUNT; i++ ) { if( mScrollbar[i]->handleKeyHere(key, mask) ) { + updateScroll(); return TRUE; } } @@ -226,38 +216,37 @@ BOOL LLScrollableContainerView::handleKeyHere(KEY key, MASK mask) BOOL LLScrollableContainerView::handleScrollWheel( S32 x, S32 y, S32 clicks ) { - for( S32 i = 0; i < SCROLLBAR_COUNT; i++ ) - { - // Note: tries vertical and then horizontal + // Give event to my child views - they may have scroll bars + // (Bad UI design, but technically possible.) + if (LLUICtrl::handleScrollWheel(x,y,clicks)) + return TRUE; + // When the vertical scrollbar is visible, scroll wheel + // only affects vertical scrolling. It's confusing to have + // scroll wheel perform both vertical and horizontal in a + // single container. + LLScrollbar* vertical = mScrollbar[VERTICAL]; + if (vertical->getVisible() + && vertical->getEnabled()) + { // Pretend the mouse is over the scrollbar - if( mScrollbar[i]->handleScrollWheel( 0, 0, clicks ) ) + if (vertical->handleScrollWheel( 0, 0, clicks ) ) { - return TRUE; + updateScroll(); } + // Always eat the event + return TRUE; } - // Eat scroll wheel event (to avoid scrolling nested containers?) - return TRUE; -} - -BOOL LLScrollableContainerView::needsToScroll(S32 x, S32 y, LLScrollableContainerView::SCROLL_ORIENTATION axis) const -{ - if(mScrollbar[axis]->getVisible()) + LLScrollbar* horizontal = mScrollbar[HORIZONTAL]; + // Test enablement and visibility for consistency with + // LLView::childrenHandleScrollWheel(). + if (horizontal->getVisible() + && horizontal->getEnabled() + && horizontal->handleScrollWheel( 0, 0, clicks ) ) { - LLRect inner_rect_local( 0, mInnerRect.getHeight(), mInnerRect.getWidth(), 0 ); - const S32 AUTOSCROLL_SIZE = 10; - if(mScrollbar[axis]->getVisible()) - { - inner_rect_local.mRight -= SCROLLBAR_SIZE; - inner_rect_local.mTop += AUTOSCROLL_SIZE; - inner_rect_local.mBottom = inner_rect_local.mTop - AUTOSCROLL_SIZE; - } - if( inner_rect_local.pointInRect( x, y ) && (mScrollbar[axis]->getDocPos() > 0) ) - { - return TRUE; - } - + updateScroll(); + return TRUE; } return FALSE; } @@ -269,65 +258,10 @@ BOOL LLScrollableContainerView::handleDragAndDrop(S32 x, S32 y, MASK mask, EAcceptance* accept, std::string& tooltip_msg) { + //S32 scrollbar_size = SCROLLBAR_SIZE; // Scroll folder view if needed. Never accepts a drag or drop. *accept = ACCEPT_NO; - BOOL handled = FALSE; - if( mScrollbar[HORIZONTAL]->getVisible() || mScrollbar[VERTICAL]->getVisible() ) - { - const S32 AUTOSCROLL_SIZE = 10; - S32 auto_scroll_speed = llround(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32()); - - LLRect inner_rect_local( 0, mInnerRect.getHeight(), mInnerRect.getWidth(), 0 ); - if( mScrollbar[HORIZONTAL]->getVisible() ) - { - inner_rect_local.mBottom += SCROLLBAR_SIZE; - } - if( mScrollbar[VERTICAL]->getVisible() ) - { - inner_rect_local.mRight -= SCROLLBAR_SIZE; - } - - if( mScrollbar[HORIZONTAL]->getVisible() ) - { - LLRect left_scroll_rect = inner_rect_local; - left_scroll_rect.mRight = AUTOSCROLL_SIZE; - if( left_scroll_rect.pointInRect( x, y ) && (mScrollbar[HORIZONTAL]->getDocPos() > 0) ) - { - mScrollbar[HORIZONTAL]->setDocPos( mScrollbar[HORIZONTAL]->getDocPos() - auto_scroll_speed ); - mAutoScrolling = TRUE; - handled = TRUE; - } - - LLRect right_scroll_rect = inner_rect_local; - right_scroll_rect.mLeft = inner_rect_local.mRight - AUTOSCROLL_SIZE; - if( right_scroll_rect.pointInRect( x, y ) && (mScrollbar[HORIZONTAL]->getDocPos() < mScrollbar[HORIZONTAL]->getDocPosMax()) ) - { - mScrollbar[HORIZONTAL]->setDocPos( mScrollbar[HORIZONTAL]->getDocPos() + auto_scroll_speed ); - mAutoScrolling = TRUE; - handled = TRUE; - } - } - if( mScrollbar[VERTICAL]->getVisible() ) - { - LLRect bottom_scroll_rect = inner_rect_local; - bottom_scroll_rect.mTop = AUTOSCROLL_SIZE + bottom_scroll_rect.mBottom; - if( bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar[VERTICAL]->getDocPos() < mScrollbar[VERTICAL]->getDocPosMax()) ) - { - mScrollbar[VERTICAL]->setDocPos( mScrollbar[VERTICAL]->getDocPos() + auto_scroll_speed ); - mAutoScrolling = TRUE; - handled = TRUE; - } - - LLRect top_scroll_rect = inner_rect_local; - top_scroll_rect.mBottom = inner_rect_local.mTop - AUTOSCROLL_SIZE; - if( top_scroll_rect.pointInRect( x, y ) && (mScrollbar[VERTICAL]->getDocPos() > 0) ) - { - mScrollbar[VERTICAL]->setDocPos( mScrollbar[VERTICAL]->getDocPos() - auto_scroll_speed ); - mAutoScrolling = TRUE; - handled = TRUE; - } - } - } + BOOL handled = autoScroll(x, y); if( !handled ) { @@ -338,6 +272,78 @@ BOOL LLScrollableContainerView::handleDragAndDrop(S32 x, S32 y, MASK mask, return TRUE; } +bool LLScrollableContainerView::autoScroll(S32 x, S32 y) +{ + S32 scrollbar_size = SCROLLBAR_SIZE; + + bool scrolling = false; + if( mScrollbar[HORIZONTAL]->getVisible() || mScrollbar[VERTICAL]->getVisible() ) + { + LLRect screen_local_extents; + screenRectToLocal(getRootView()->getLocalRect(), &screen_local_extents); + + LLRect inner_rect_local( 0, mInnerRect.getHeight(), mInnerRect.getWidth(), 0 ); + if( mScrollbar[HORIZONTAL]->getVisible() ) + { + inner_rect_local.mBottom += scrollbar_size; + } + if( mScrollbar[VERTICAL]->getVisible() ) + { + inner_rect_local.mRight -= scrollbar_size; + } + + // clip rect against root view + inner_rect_local.intersectWith(screen_local_extents); + + S32 auto_scroll_speed = llround(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32()); + // autoscroll region should take up no more than one third of visible scroller area + S32 auto_scroll_region_width = llmin(inner_rect_local.getWidth() / 3, 10); + S32 auto_scroll_region_height = llmin(inner_rect_local.getHeight() / 3, 10); + + if( mScrollbar[HORIZONTAL]->getVisible() ) + { + LLRect left_scroll_rect = screen_local_extents; + left_scroll_rect.mRight = inner_rect_local.mLeft + auto_scroll_region_width; + if( left_scroll_rect.pointInRect( x, y ) && (mScrollbar[HORIZONTAL]->getDocPos() > 0) ) + { + mScrollbar[HORIZONTAL]->setDocPos( mScrollbar[HORIZONTAL]->getDocPos() - auto_scroll_speed ); + mAutoScrolling = TRUE; + scrolling = true; + } + + LLRect right_scroll_rect = screen_local_extents; + right_scroll_rect.mLeft = inner_rect_local.mRight - auto_scroll_region_width; + if( right_scroll_rect.pointInRect( x, y ) && (mScrollbar[HORIZONTAL]->getDocPos() < mScrollbar[HORIZONTAL]->getDocPosMax()) ) + { + mScrollbar[HORIZONTAL]->setDocPos( mScrollbar[HORIZONTAL]->getDocPos() + auto_scroll_speed ); + mAutoScrolling = TRUE; + scrolling = true; + } + } + if( mScrollbar[VERTICAL]->getVisible() ) + { + LLRect bottom_scroll_rect = screen_local_extents; + bottom_scroll_rect.mTop = inner_rect_local.mBottom + auto_scroll_region_height; + if( bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar[VERTICAL]->getDocPos() < mScrollbar[VERTICAL]->getDocPosMax()) ) + { + mScrollbar[VERTICAL]->setDocPos( mScrollbar[VERTICAL]->getDocPos() + auto_scroll_speed ); + mAutoScrolling = TRUE; + scrolling = true; + } + + LLRect top_scroll_rect = screen_local_extents; + top_scroll_rect.mBottom = inner_rect_local.mTop - auto_scroll_region_height; + if( top_scroll_rect.pointInRect( x, y ) && (mScrollbar[VERTICAL]->getDocPos() > 0) ) + { + mScrollbar[VERTICAL]->setDocPos( mScrollbar[VERTICAL]->getDocPos() - auto_scroll_speed ); + mAutoScrolling = TRUE; + scrolling = true; + } + } + } + return scrolling; +} + BOOL LLScrollableContainerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect) { @@ -368,42 +374,44 @@ BOOL LLScrollableContainerView::handleToolTip(S32 x, S32 y, std::string& msg, LL void LLScrollableContainerView::calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const { - const LLRect& rect = mScrolledView->getRect(); - calcVisibleSize(rect, visible_width, visible_height, show_h_scrollbar, show_v_scrollbar); -} - -void LLScrollableContainerView::calcVisibleSize( const LLRect& doc_rect, S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const -{ + const LLRect& doc_rect = getScrolledViewRect(); + S32 scrollbar_size = SCROLLBAR_SIZE; S32 doc_width = doc_rect.getWidth(); S32 doc_height = doc_rect.getHeight(); - *visible_width = getRect().getWidth() - 2 * mBorder->getBorderWidth(); - *visible_height = getRect().getHeight() - 2 * mBorder->getBorderWidth(); + S32 border_width = getBorderWidth(); + *visible_width = getRect().getWidth() - 2 * border_width; + *visible_height = getRect().getHeight() - 2 * border_width; *show_v_scrollbar = FALSE; - if( *visible_height < doc_height ) - { - *show_v_scrollbar = TRUE; - *visible_width -= SCROLLBAR_SIZE; - } - *show_h_scrollbar = FALSE; - if( *visible_width < doc_width ) - { - *show_h_scrollbar = TRUE; - *visible_height -= SCROLLBAR_SIZE; - // Must retest now that visible_height has changed - if( !*show_v_scrollbar && (*visible_height < doc_height) ) + if (!mHideScrollbar) + { + if( *visible_height < doc_height ) { *show_v_scrollbar = TRUE; - *visible_width -= SCROLLBAR_SIZE; + *visible_width -= scrollbar_size; + } + + if( *visible_width < doc_width ) + { + *show_h_scrollbar = TRUE; + *visible_height -= scrollbar_size; + + // Must retest now that visible_height has changed + if( !*show_v_scrollbar && (*visible_height < doc_height) ) + { + *show_v_scrollbar = TRUE; + *visible_width -= scrollbar_size; + } } } } void LLScrollableContainerView::draw() { + S32 scrollbar_size = SCROLLBAR_SIZE; if (mAutoScrolling) { // add acceleration to autoscroll @@ -411,76 +419,79 @@ void LLScrollableContainerView::draw() } else { - // reset to minimum - mAutoScrollRate = MIN_AUTO_SCROLL_RATE; + // reset to minimum for next time + mAutoScrollRate = mMinAutoScrollRate; } - // clear this flag to be set on next call to handleDragAndDrop + // clear this flag to be set on next call to autoScroll mAutoScrolling = FALSE; // auto-focus when scrollbar active // this allows us to capture user intent (i.e. stop automatically scrolling the view/etc) - if (!gFocusMgr.childHasKeyboardFocus(this) && - (mScrollbar[VERTICAL]->hasMouseCapture() || mScrollbar[HORIZONTAL]->hasMouseCapture())) + if (!hasFocus() + && (mScrollbar[VERTICAL]->hasMouseCapture() || mScrollbar[HORIZONTAL]->hasMouseCapture())) { focusFirstItem(); } - // Draw background - if( mIsOpaque ) + if (getRect().isValid()) { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4fv( mBackgroundColor.mV ); - gl_rect_2d( mInnerRect ); - } + // Draw background + if( mIsOpaque ) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4fv( mBackgroundColor.mV ); + gl_rect_2d( mInnerRect ); + } - // Draw mScrolledViews and update scroll bars. - // get a scissor region ready, and draw the scrolling view. The - // scissor region ensures that we don't draw outside of the bounds - // of the rectangle. - if( mScrolledView ) - { - updateScroll(); - - // Draw the scrolled area. + // Draw mScrolledViews and update scroll bars. + // get a scissor region ready, and draw the scrolling view. The + // scissor region ensures that we don't draw outside of the bounds + // of the rectangle. + if( mScrolledView ) { - S32 visible_width = 0; - S32 visible_height = 0; - BOOL show_v_scrollbar = FALSE; - BOOL show_h_scrollbar = FALSE; - calcVisibleSize( mScrolledView->getRect(), &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); + updateScroll(); - LLLocalClipRect clip(LLRect(mInnerRect.mLeft, - mInnerRect.mBottom + (show_h_scrollbar ? SCROLLBAR_SIZE : 0) + visible_height, - visible_width, - mInnerRect.mBottom + (show_h_scrollbar ? SCROLLBAR_SIZE : 0) - )); - drawChild(mScrolledView); + // Draw the scrolled area. + { + S32 visible_width = 0; + S32 visible_height = 0; + BOOL show_v_scrollbar = FALSE; + BOOL show_h_scrollbar = FALSE; + calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); + + LLLocalClipRect clip(LLRect(mInnerRect.mLeft, + mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + visible_height, + mInnerRect.mRight - (show_v_scrollbar ? scrollbar_size: 0), + mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + )); + drawChild(mScrolledView); + } } - } - // Highlight border if a child of this container has keyboard focus - if( mBorder->getVisible() ) - { - mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus(this) ); - } + // Highlight border if a child of this container has keyboard focus + if( mBorder->getVisible() ) + { + mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus(this) ); + } - // Draw all children except mScrolledView - // Note: scrollbars have been adjusted by above drawing code - for (child_list_const_reverse_iter_t child_iter = getChildList()->rbegin(); - child_iter != getChildList()->rend(); ++child_iter) - { - LLView *viewp = *child_iter; - if( sDebugRects ) + // Draw all children except mScrolledView + // Note: scrollbars have been adjusted by above drawing code + for (child_list_const_reverse_iter_t child_iter = getChildList()->rbegin(); + child_iter != getChildList()->rend(); ++child_iter) { - sDepth++; - } - if( (viewp != mScrolledView) && viewp->getVisible() ) - { - drawChild(viewp); - } - if( sDebugRects ) - { - sDepth--; + LLView *viewp = *child_iter; + if( sDebugRects ) + { + sDepth++; + } + if( (viewp != mScrolledView) && viewp->getVisible() ) + { + drawChild(viewp); + } + if( sDebugRects ) + { + sDepth--; + } } } @@ -491,8 +502,30 @@ void LLScrollableContainerView::draw() } // end draw +bool LLScrollableContainerView::addChild(LLView* view, S32 tab_group) +{ + if (!mScrolledView) + { + // Use the first panel or container as the scrollable view (bit of a hack) + mScrolledView = view; + } + + bool ret_val = LLView::addChild(view, tab_group); + + //bring the scrollbars to the front + sendChildToFront( mScrollbar[HORIZONTAL] ); + sendChildToFront( mScrollbar[VERTICAL] ); + + return ret_val; +} + void LLScrollableContainerView::updateScroll() { + if (!mScrolledView) + { + return; + } + S32 scrollbar_size = SCROLLBAR_SIZE; LLRect doc_rect = mScrolledView->getRect(); S32 doc_width = doc_rect.getWidth(); S32 doc_height = doc_rect.getHeight(); @@ -500,9 +533,9 @@ void LLScrollableContainerView::updateScroll() S32 visible_height = 0; BOOL show_v_scrollbar = FALSE; BOOL show_h_scrollbar = FALSE; - calcVisibleSize( doc_rect, &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); + calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); - S32 border_width = mBorder->getBorderWidth(); + S32 border_width = getBorderWidth(); if( show_v_scrollbar ) { if( doc_rect.mTop < getRect().getHeight() - border_width ) @@ -516,15 +549,15 @@ void LLScrollableContainerView::updateScroll() S32 v_scrollbar_height = visible_height; if( !show_h_scrollbar && mReserveScrollCorner ) { - v_scrollbar_height -= SCROLLBAR_SIZE; + v_scrollbar_height -= scrollbar_size; } - mScrollbar[VERTICAL]->reshape( SCROLLBAR_SIZE, v_scrollbar_height, TRUE ); + mScrollbar[VERTICAL]->reshape( scrollbar_size, v_scrollbar_height, TRUE ); // Make room for the horizontal scrollbar (or not) S32 v_scrollbar_offset = 0; if( show_h_scrollbar || mReserveScrollCorner ) { - v_scrollbar_offset = SCROLLBAR_SIZE; + v_scrollbar_offset = scrollbar_size; } LLRect r = mScrollbar[VERTICAL]->getRect(); r.translate( 0, mInnerRect.mBottom - r.mBottom + v_scrollbar_offset ); @@ -554,9 +587,9 @@ void LLScrollableContainerView::updateScroll() S32 h_scrollbar_width = visible_width; if( !show_v_scrollbar && mReserveScrollCorner ) { - h_scrollbar_width -= SCROLLBAR_SIZE; + h_scrollbar_width -= scrollbar_size; } - mScrollbar[HORIZONTAL]->reshape( h_scrollbar_width, SCROLLBAR_SIZE, TRUE ); + mScrollbar[HORIZONTAL]->reshape( h_scrollbar_width, scrollbar_size, TRUE ); } else { @@ -576,101 +609,115 @@ void LLScrollableContainerView::updateScroll() void LLScrollableContainerView::setBorderVisible(BOOL b) { mBorder->setVisible( b ); + // Recompute inner rect, as border visibility changes it + mInnerRect = getLocalRect(); + mInnerRect.stretch( -getBorderWidth() ); } -// Scroll so that as much of rect as possible is showing (where rect is defined in the space of scroller view, not scrolled) -void LLScrollableContainerView::scrollToShowRect(const LLRect& rect, const LLCoordGL& desired_offset) +LLRect LLScrollableContainerView::getVisibleContentRect() +{ + updateScroll(); + LLRect visible_rect = getContentWindowRect(); + LLRect contents_rect = mScrolledView->getRect(); + visible_rect.translate(-contents_rect.mLeft, -contents_rect.mBottom); + return visible_rect; +} +LLRect LLScrollableContainerView::getContentWindowRect() +{ + updateScroll(); + LLRect scroller_view_rect; + S32 visible_width = 0; + S32 visible_height = 0; + BOOL show_h_scrollbar = FALSE; + BOOL show_v_scrollbar = FALSE; + calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); + S32 border_width = getBorderWidth(); + scroller_view_rect.setOriginAndSize(border_width, + show_h_scrollbar ? mScrollbar[HORIZONTAL]->getRect().mTop : border_width, + visible_width, + visible_height); + return scroller_view_rect; +} + +// rect is in document coordinates, constraint is in display coordinates relative to content window rect +void LLScrollableContainerView::scrollToShowRect(const LLRect& rect, const LLRect& constraint) { if (!mScrolledView) { - llwarns << "LLScrollableContainerView::scrollToShowRect with no view!" << llendl; + llwarns << "LLScrollContainer::scrollToShowRect with no view!" << llendl; return; } - S32 visible_width = 0; - S32 visible_height = 0; - BOOL show_v_scrollbar = FALSE; - BOOL show_h_scrollbar = FALSE; - const LLRect& scrolled_rect = mScrolledView->getRect(); - calcVisibleSize( scrolled_rect, &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); + LLRect content_window_rect = getContentWindowRect(); + // get document rect + LLRect scrolled_rect = mScrolledView->getRect(); - // can't be so far left that right side of rect goes off screen, or so far right that left side does - S32 horiz_offset = llclamp(desired_offset.mX, llmin(0, -visible_width + rect.getWidth()), 0); - // can't be so high that bottom of rect goes off screen, or so low that top does - S32 vert_offset = llclamp(desired_offset.mY, 0, llmax(0, visible_height - rect.getHeight())); + // shrink target rect to fit within constraint region, biasing towards top left + LLRect rect_to_constrain = rect; + rect_to_constrain.mBottom = llmax(rect_to_constrain.mBottom, rect_to_constrain.mTop - constraint.getHeight()); + rect_to_constrain.mRight = llmin(rect_to_constrain.mRight, rect_to_constrain.mLeft + constraint.getWidth()); - // Vertical - // 1. First make sure the top is visible - // 2. Then, if possible without hiding the top, make the bottom visible. - S32 vert_pos = mScrollbar[VERTICAL]->getDocPos(); + // calculate allowable positions for scroller window in document coordinates + LLRect allowable_scroll_rect(rect_to_constrain.mRight - constraint.mRight, + rect_to_constrain.mBottom - constraint.mBottom, + rect_to_constrain.mLeft - constraint.mLeft, + rect_to_constrain.mTop - constraint.mTop); - // find scrollbar position to get top of rect on screen (scrolling up) - S32 top_offset = scrolled_rect.mTop - rect.mTop - vert_offset; - // find scrollbar position to get bottom of rect on screen (scrolling down) - S32 bottom_offset = vert_offset == 0 ? scrolled_rect.mTop - rect.mBottom - visible_height : top_offset; - // scroll up far enough to see top or scroll down just enough if item is bigger than visual area - if( vert_pos >= top_offset || visible_height < rect.getHeight()) - { - vert_pos = top_offset; - } - // else scroll down far enough to see bottom - else - if( vert_pos <= bottom_offset ) - { - vert_pos = bottom_offset; - } + // translate from allowable region for lower left corner to upper left corner + allowable_scroll_rect.translate(0, content_window_rect.getHeight()); + + S32 vert_pos = llclamp(mScrollbar[VERTICAL]->getDocPos(), + mScrollbar[VERTICAL]->getDocSize() - allowable_scroll_rect.mTop, // min vertical scroll + mScrollbar[VERTICAL]->getDocSize() - allowable_scroll_rect.mBottom); // max vertical scroll mScrollbar[VERTICAL]->setDocSize( scrolled_rect.getHeight() ); - mScrollbar[VERTICAL]->setPageSize( visible_height ); + mScrollbar[VERTICAL]->setPageSize( content_window_rect.getHeight() ); mScrollbar[VERTICAL]->setDocPos( vert_pos ); - // Horizontal - // 1. First make sure left side is visible - // 2. Then, if possible without hiding the left side, make the right side visible. - S32 horiz_pos = mScrollbar[HORIZONTAL]->getDocPos(); - S32 left_offset = rect.mLeft - scrolled_rect.mLeft + horiz_offset; - S32 right_offset = horiz_offset == 0 ? rect.mRight - scrolled_rect.mLeft - visible_width : left_offset; + S32 horizontal_pos = llclamp(mScrollbar[HORIZONTAL]->getDocPos(), + allowable_scroll_rect.mLeft, + allowable_scroll_rect.mRight); - if( horiz_pos >= left_offset || visible_width < rect.getWidth() ) - { - horiz_pos = left_offset; - } - else if( horiz_pos <= right_offset ) - { - horiz_pos = right_offset; - } - mScrollbar[HORIZONTAL]->setDocSize( scrolled_rect.getWidth() ); - mScrollbar[HORIZONTAL]->setPageSize( visible_width ); - mScrollbar[HORIZONTAL]->setDocPos( horiz_pos ); + mScrollbar[HORIZONTAL]->setPageSize( content_window_rect.getWidth() ); + mScrollbar[HORIZONTAL]->setDocPos( horizontal_pos ); // propagate scroll to document updateScroll(); + + // In case we are in accordion tab notify parent to show selected rectangle + LLRect screen_rc; + localRectToScreen(rect_to_constrain, &screen_rc); + notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue())); } void LLScrollableContainerView::pageUp(S32 overlap) { mScrollbar[VERTICAL]->pageUp(overlap); + updateScroll(); } void LLScrollableContainerView::pageDown(S32 overlap) { mScrollbar[VERTICAL]->pageDown(overlap); + updateScroll(); } void LLScrollableContainerView::goToTop() { mScrollbar[VERTICAL]->setDocPos(0); + updateScroll(); } void LLScrollableContainerView::goToBottom() { mScrollbar[VERTICAL]->setDocPos(mScrollbar[VERTICAL]->getDocSize()); + updateScroll(); } S32 LLScrollableContainerView::getBorderWidth() const { - if (mBorder) + if (mBorder && mBorder->getVisible()) { return mBorder->getBorderWidth(); } diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index 70fc9087d..a5002a341 100644 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -63,30 +63,29 @@ public: LLScrollableContainerView( const std::string& name, const LLRect& rect, LLView* scrolled_view, BOOL is_opaque = FALSE, const LLColor4& bg_color = LLColor4(0,0,0,0) ); - LLScrollableContainerView( const std::string& name, const LLRect& rect, - LLUICtrl* scrolled_ctrl, BOOL is_opaque = FALSE, - const LLColor4& bg_color = LLColor4(0,0,0,0) ); virtual ~LLScrollableContainerView( void ); void setScrolledView(LLView* view) { mScrolledView = view; } virtual void setValue(const LLSD& value) { mInnerRect.setValue(value); } - void calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const; - void calcVisibleSize( const LLRect& doc_rect, S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const; void setBorderVisible( BOOL b ); - void scrollToShowRect( const LLRect& rect, const LLCoordGL& desired_offset ); + void scrollToShowRect( const LLRect& rect, const LLRect& constraint); + void scrollToShowRect( const LLRect& rect) { scrollToShowRect(rect, LLRect(0, mInnerRect.getHeight(), mInnerRect.getWidth(), 0)); } + void setReserveScrollCorner( BOOL b ) { mReserveScrollCorner = b; } - const LLRect& getScrolledViewRect() const { return mScrolledView->getRect(); } + LLRect getVisibleContentRect(); + LLRect getContentWindowRect(); + const LLRect& getScrolledViewRect() const { return mScrolledView ? mScrolledView->getRect() : LLRect::null; } void pageUp(S32 overlap = 0); void pageDown(S32 overlap = 0); void goToTop(); void goToBottom(); + bool isAtTop() { return mScrollbar[VERTICAL]->isAtBeginning(); } + bool isAtBottom() { return mScrollbar[VERTICAL]->isAtEnd(); } S32 getBorderWidth() const; - BOOL needsToScroll(S32 x, S32 y, SCROLL_ORIENTATION axis) const; - // LLView functionality virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); virtual BOOL handleKeyHere(KEY key, MASK mask); @@ -99,8 +98,10 @@ public: virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); virtual void draw(); - - virtual LLXMLNodePtr getXML(bool save_children = true) const; + virtual bool addChild(LLView* view, S32 tab_group = 0); + + bool autoScroll(S32 x, S32 y); + virtual LLXMLNodePtr getXML(bool save_children) const; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); private: @@ -110,6 +111,9 @@ private: virtual void scrollHorizontal( S32 new_pos ); virtual void scrollVertical( S32 new_pos ); void updateScroll(); +public: + void calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const; +private: LLScrollbar* mScrollbar[SCROLLBAR_COUNT]; LLView* mScrolledView; @@ -121,6 +125,9 @@ private: BOOL mReserveScrollCorner; BOOL mAutoScrolling; F32 mAutoScrollRate; + F32 mMinAutoScrollRate; + F32 mMaxAutoScrollRate; + bool mHideScrollbar; }; diff --git a/indra/llui/llscrollingpanellist.cpp b/indra/llui/llscrollingpanellist.cpp index c2afb78f7..8aa8b9fe3 100644 --- a/indra/llui/llscrollingpanellist.cpp +++ b/indra/llui/llscrollingpanellist.cpp @@ -52,7 +52,7 @@ void LLScrollingPanelList::clearPanels() void LLScrollingPanelList::addPanel( LLScrollingPanel* panel ) { - addChildAtEnd( panel ); + addChildInBack( panel ); mPanelList.push_front( panel ); const S32 GAP_BETWEEN_PANELS = 6; diff --git a/indra/llui/llscrollingpanellist.h b/indra/llui/llscrollingpanellist.h index 96604270d..946073b97 100644 --- a/indra/llui/llscrollingpanellist.h +++ b/indra/llui/llscrollingpanellist.h @@ -29,6 +29,9 @@ * $/LicenseInfo$ */ +#ifndef LL_LLSCROLLINGPANELLIST_H +#define LL_LLSCROLLINGPANELLIST_H + #include #include "llui.h" @@ -56,6 +59,8 @@ public: LLScrollingPanelList(const std::string& name, const LLRect& rect) : LLUICtrl(name, rect, TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_BOTTOM ) {} + typedef std::deque panel_list_t; + virtual void setValue(const LLSD& value) {}; virtual void draw(); @@ -64,11 +69,16 @@ public: void addPanel( LLScrollingPanel* panel ); void updatePanels(BOOL allow_modify); + const panel_list_t& getPanelList() { return mPanelList; } + virtual LLXMLNodePtr getXML(bool save_children = true) const; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); private: void updatePanelVisiblilty(); - std::deque mPanelList; + + panel_list_t mPanelList; }; + +#endif //LL_LLSCROLLINGPANELLIST_H diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 01c3a4731..e4ad47118 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -117,7 +117,11 @@ LLScrollListIcon::LLScrollListIcon(LLUIImagePtr icon, S32 width) LLScrollListIcon::LLScrollListIcon(const LLSD& value, S32 width) : LLScrollListCell(width), - mColor(LLColor4::white) + // + mCallback(NULL), + mUserData(NULL), + // + mColor(LLColor4::white) { setValue(value); } @@ -637,6 +641,7 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, : LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data), mLineHeight(0), mScrollLines(0), + mMouseWheelOpaque(true), mPageLines(0), mHeadingHeight(20), mMaxSelectable(0), @@ -745,11 +750,6 @@ S32 LLScrollListCtrl::getSearchColumn() LLScrollListCtrl::~LLScrollListCtrl() { std::for_each(mItemList.begin(), mItemList.end(), DeletePointer()); - - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } } @@ -1951,6 +1951,12 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks) BOOL handled = FALSE; // Pretend the mouse is over the scrollbar handled = mScrollbar->handleScrollWheel( 0, 0, clicks ); + + if (mMouseWheelOpaque) + { + return TRUE; + } + return handled; } @@ -2129,6 +2135,8 @@ BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask) mSelectionChanged = FALSE; handleClick(x, y, mask); + + setFocus(TRUE); } return TRUE; @@ -2364,7 +2372,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mCanSelect) { // Ignore capslock - mask = mask; + //mask = mask; //Why was this here? if (mask == MASK_NONE) { @@ -2843,6 +2851,8 @@ LLXMLNodePtr LLScrollListCtrl::getXML(bool save_children) const node->createChild("draw_stripes", TRUE)->setBoolValue(mDrawStripes); node->createChild("column_padding", TRUE)->setIntValue(mColumnPadding); + + node->createChild("mouse_wheel_opaque", TRUE)->setBoolValue(mMouseWheelOpaque); addColorXML(node, mBgWriteableColor, "bg_writeable_color", "ScrollBgWriteableColor"); addColorXML(node, mBgReadOnlyColor, "bg_read_only_color", "ScrollBgReadOnlyColor"); @@ -2970,6 +2980,9 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac BOOL sort_ascending = TRUE; node->getAttributeBOOL("sort_ascending", sort_ascending); + + BOOL mouse_wheel_opaque = TRUE; + node->getAttributeBOOL("mouse_wheel_opaque", mouse_wheel_opaque); LLUICtrlCallback callback = NULL; @@ -2994,6 +3007,8 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac scroll_list->initFromXML(node, parent); scroll_list->setSearchColumn(search_column); + + scroll_list->mMouseWheelOpaque = mouse_wheel_opaque; LLSD columns; S32 index = 0; @@ -3684,9 +3699,9 @@ LLColumnHeader::LLColumnHeader(const std::string& label, const LLRect &rect, LLS mButton->setTabStop(FALSE); // require at least two frames between mouse down and mouse up event to capture intentional "hold" not just bad framerate mButton->setHeldDownDelay(LLUI::sConfigGroup->getF32("ColumnHeaderDropDownDelay"), 2); - mButton->setHeldDownCallback(onHeldDown); - mButton->setClickedCallback(onClick); - mButton->setMouseDownCallback(onMouseDown); + mButton->setHeldDownCallback(boost::bind(&LLColumnHeader::onHeldDown, this)); + mButton->setClickedCallback(boost::bind(&LLColumnHeader::onClick, this)); + mButton->setMouseDownCallback(boost::bind(&LLColumnHeader::onMouseDown, this)); mButton->setCallbackUserData(this); mButton->setToolTip(label); @@ -3848,8 +3863,8 @@ void LLColumnHeader::setImage(const std::string &image_name) { if (mButton) { - mButton->setImageSelected(image_name); - mButton->setImageUnselected(image_name); + mButton->setImageSelected(LLUI::getUIImage(image_name)); + mButton->setImageUnselected(LLUI::getUIImage(image_name)); } } @@ -3885,6 +3900,8 @@ void LLColumnHeader::onClick(void* user_data) // propagate new sort order to sort order list headerp->mList->selectNthItem(column->mParentCtrl->getSortAscending() ? 0 : 1); + + headerp->mList->setFocus(TRUE); } //static diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 10b7e13a2..ada8032f1 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -671,6 +671,7 @@ private: BOOL mCommitOnSelectionChange; BOOL mSelectionChanged; BOOL mNeedsScroll; + BOOL mMouseWheelOpaque; BOOL mCanSelect; BOOL mDisplayColumnHeaders; BOOL mColumnsDirty; diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp index 60907fd58..41c4c0560 100644 --- a/indra/llui/llsliderctrl.cpp +++ b/indra/llui/llsliderctrl.cpp @@ -121,7 +121,7 @@ LLSliderCtrl::LLSliderCtrl(const std::string& name, const LLRect& rect, &LLLineEditor::prevalidateFloat ); mEditor->setFollowsLeft(); mEditor->setFollowsBottom(); - mEditor->setFocusReceivedCallback( &LLSliderCtrl::onEditorGainFocus, this ); + mEditor->setFocusReceivedCallback( boost::bind(&LLSliderCtrl::onFocusReceived, this) ); mEditor->setIgnoreTab(TRUE); // don't do this, as selecting the entire text is single clicking in some cases // and double clicking in others @@ -140,17 +140,6 @@ LLSliderCtrl::LLSliderCtrl(const std::string& name, const LLRect& rect, updateText(); } - -// static -void LLSliderCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata ) -{ - LLSliderCtrl* self = (LLSliderCtrl*) userdata; - llassert( caller == self->mEditor ); - - self->onFocusReceived(); -} - - void LLSliderCtrl::setValue(F32 v, BOOL from_event) { mSlider->setValue( v, from_event ); diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h index 68748eb4d..f7c321235 100644 --- a/indra/llui/llsliderctrl.h +++ b/indra/llui/llsliderctrl.h @@ -117,7 +117,6 @@ public: static void onSliderCommit(LLUICtrl* caller, void* userdata); static void onEditorCommit(LLUICtrl* caller, void* userdata); - static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); private: diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index ce13a2697..4db05f0cc 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -101,7 +101,7 @@ LLSpinCtrl::LLSpinCtrl( const std::string& name, const LLRect& rect, const std:: &LLSpinCtrl::onUpBtn, this, LLFontGL::getFontSansSerif() ); mUpBtn->setFollowsLeft(); mUpBtn->setFollowsBottom(); - mUpBtn->setHeldDownCallback( &LLSpinCtrl::onUpBtn ); + mUpBtn->setHeldDownCallback(boost::bind(&LLSpinCtrl::onUpBtn,this)); mUpBtn->setTabStop(FALSE); addChild(mUpBtn); @@ -115,7 +115,7 @@ LLSpinCtrl::LLSpinCtrl( const std::string& name, const LLRect& rect, const std:: &LLSpinCtrl::onDownBtn, this, LLFontGL::getFontSansSerif() ); mDownBtn->setFollowsLeft(); mDownBtn->setFollowsBottom(); - mDownBtn->setHeldDownCallback( &LLSpinCtrl::onDownBtn ); + mDownBtn->setHeldDownCallback(boost::bind(&LLSpinCtrl::onDownBtn,this)); mDownBtn->setTabStop(FALSE); addChild(mDownBtn); @@ -126,7 +126,7 @@ LLSpinCtrl::LLSpinCtrl( const std::string& name, const LLRect& rect, const std:: &LLLineEditor::prevalidateASCII ); mEditor->setFollowsLeft(); mEditor->setFollowsBottom(); - mEditor->setFocusReceivedCallback( &LLSpinCtrl::onEditorGainFocus, this ); + mEditor->setFocusReceivedCallback( boost::bind(&LLSpinCtrl::onFocusReceived, this) ); //RN: this seems to be a BAD IDEA, as it makes the editor behavior different when it has focus // than when it doesn't. Instead, if you always have to double click to select all the text, // it's easier to understand @@ -243,15 +243,6 @@ void LLSpinCtrl::onDownBtn( void *userdata ) } } -// static -void LLSpinCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata ) -{ - LLSpinCtrl* self = (LLSpinCtrl*) userdata; - llassert( caller == self->mEditor ); - - self->onFocusReceived(); -} - void LLSpinCtrl::setValue(const LLSD& value ) { F32 v = (F32)value.asReal(); diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h index b9d94e57c..9e53c362f 100644 --- a/indra/llui/llspinctrl.h +++ b/indra/llui/llspinctrl.h @@ -110,7 +110,6 @@ public: virtual void draw(); static void onEditorCommit(LLUICtrl* caller, void* userdata); - static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); static void onUpBtn(void *userdata); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index eeff21cdf..7d3bb20c4 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -69,19 +69,38 @@ const S32 TABCNTRV_PAD = 0; static LLRegisterWidget r("tab_container"); +// Structure used to map tab buttons to and from tab panels +class LLTabTuple +{ +public: + LLTabTuple( LLTabContainer* c, LLPanel* p, LLButton* b, LLTextBox* placeholder = NULL) + : + mTabContainer(c), + mTabPanel(p), + mButton(b), + mOldState(FALSE), + mPlaceholderText(placeholder), + mPadding(0) + {} + + LLTabContainer* mTabContainer; + LLPanel* mTabPanel; + LLButton* mButton; + BOOL mOldState; + LLTextBox* mPlaceholderText; + S32 mPadding; +}; + LLTabContainer::LLTabContainer(const std::string& name, const LLRect& rect, TabPosition pos, BOOL bordered, BOOL is_vertical ) : LLPanel(name, rect, bordered), mCurrentTabIdx(-1), - mNextTabIdx(-1), mTabsHidden(FALSE), mScrolled(FALSE), mScrollPos(0), mScrollPosPixels(0), mMaxScrollPos(0), - mCloseCallback( NULL ), - mCallbackUserdata( NULL ), mTitleBox(NULL), mTopBorderHeight(LLPANEL_BORDER_WIDTH), mTabPosition(pos), @@ -196,9 +215,9 @@ void LLTabContainer::draw() } } - setScrollPosPixels((S32)lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f))); + setScrollPosPixels(mIsVertical ? target_pixel_scroll : lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f))); - BOOL has_scroll_arrows = (mMaxScrollPos > 0) || (mScrollPosPixels > 0); + BOOL has_scroll_arrows = !getTabsHidden() && ((mMaxScrollPos > 0) || (mScrollPosPixels > 0)); if (!mIsVertical) { mJumpPrevArrowBtn->setVisible( has_scroll_arrows ); @@ -221,13 +240,22 @@ void LLTabContainer::draw() } // Hide all the buttons - for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + if (getTabsHidden() || mIsVertical) { - LLTabTuple* tuple = *iter; - tuple->mButton->setVisible( FALSE ); + for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + { + LLTabTuple* tuple = *iter; + tuple->mButton->setVisible( FALSE ); + } } - LLPanel::draw(); + { + LLRect clip_rect = getLocalRect(); + clip_rect.mLeft+=(LLPANEL_BORDER_WIDTH + 2); + clip_rect.mRight-=(LLPANEL_BORDER_WIDTH + 2); + LLLocalClipRect clip(clip_rect); + LLPanel::draw(); + } // if tabs are hidden, don't draw them and leave them in the invisible state if (!getTabsHidden()) @@ -241,19 +269,10 @@ void LLTabContainer::draw() // Draw some of the buttons... LLRect clip_rect = getLocalRect(); - if (has_scroll_arrows) + if (has_scroll_arrows && mIsVertical) { - // ...but clip them. - if (mIsVertical) - { - clip_rect.mBottom = mNextArrowBtn->getRect().mTop + 3*TABCNTRV_PAD; - clip_rect.mTop = mPrevArrowBtn->getRect().mBottom - 3*TABCNTRV_PAD; - } - else - { - clip_rect.mLeft = mPrevArrowBtn->getRect().mRight; - clip_rect.mRight = mNextArrowBtn->getRect().mLeft; - } + clip_rect.mTop = top - getScrollPosPixels(); + clip_rect.mBottom = TABCNTR_ARROW_BTN_SIZE+1; } LLLocalClipRect clip(clip_rect); @@ -285,12 +304,13 @@ void LLTabContainer::draw() } } } - LLUI::pushMatrix(); + else { + LLUI::pushMatrix(); LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f); tuple->mButton->draw(); + LLUI::popMatrix(); } - LLUI::popMatrix(); idx++; } @@ -320,7 +340,7 @@ void LLTabContainer::draw() BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) { BOOL handled = FALSE; - BOOL has_scroll_arrows = (getMaxScrollPos() > 0); + BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden(); if (has_scroll_arrows) { @@ -355,7 +375,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) } S32 tab_count = getTabCount(); - if (tab_count > 0) + if (tab_count > 0 && !getTabsHidden()) { LLTabTuple* firsttuple = getTab(0); LLRect tab_rect; @@ -379,6 +399,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) index = llclamp(index, 0, tab_count-1); LLButton* tab_button = getTab(index)->mButton; gFocusMgr.setMouseCapture(this); + tab_button->setFocus(TRUE); gFocusMgr.setKeyboardFocus(tab_button); } } @@ -389,7 +410,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask ) { BOOL handled = FALSE; - BOOL has_scroll_arrows = (getMaxScrollPos() > 0); + BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden(); if (has_scroll_arrows) { @@ -431,7 +452,7 @@ BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask ) BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) { BOOL handled = FALSE; - BOOL has_scroll_arrows = (getMaxScrollPos() > 0); + BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden(); if (has_scroll_arrows) { @@ -487,7 +508,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect ) { BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect ); - if (!handled && getTabCount() > 0) + if (!handled && getTabCount() > 0 && !getTabsHidden()) { LLTabTuple* firsttuple = getTab(0); @@ -523,12 +544,6 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic } } } - - for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) - { - LLTabTuple* tuple = *iter; - tuple->mButton->setVisible( FALSE ); - } } return handled; } @@ -552,7 +567,7 @@ BOOL LLTabContainer::handleKeyHere(KEY key, MASK mask) { if (getCurrentPanel()) { - getCurrentPanel()->setFocus(TRUE); + getCurrentPanel()->setFocus(TRUE); } } @@ -633,59 +648,63 @@ LLXMLNodePtr LLTabContainer::getXML(bool save_children) const // virtual BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, std::string &tooltip) { - bool const has_scroll_arrows = (getMaxScrollPos() > 0); + BOOL has_scroll_arrows = (getMaxScrollPos() > 0); - LLButton* button = NULL; - if (has_scroll_arrows) + if(!getTabsHidden()) { - // We're dragging an inventory item. Check if we're hovering over scroll arrows of this tab container. - if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y)) + // In that case, we'll open the hovered tab while dragging and dropping items. + // This allows for drilling through tabs. + if (mDragAndDropDelayTimer.getStarted()) { - button = mJumpPrevArrowBtn; - } - else if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y)) - { - button = mJumpNextArrowBtn; - } - else if (mPrevArrowBtn->getRect().pointInRect(x, y)) - { - button = mPrevArrowBtn; - } - else if (mNextArrowBtn->getRect().pointInRect(x, y)) - { - button = mNextArrowBtn; - } - if (button) - { - if (mDragAndDropDelayTimer.getStarted() && mDragAndDropDelayTimer.hasExpired()) + if (mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME) { - // We've been hovering (another) SCROLL_DELAY_TIME seconds. Emulate a button press. - button->onCommit(); - // Reset the timer. - mDragAndDropDelayTimer.start(SCROLL_DELAY_TIME); - } - else if (!mDragAndDropDelayTimer.getStarted()) - { - // We just entered the arrow. Start the timer. - mDragAndDropDelayTimer.start(SCROLL_DELAY_TIME); + if (has_scroll_arrows) + { + if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y)) + { + S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft; + S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom; + mJumpPrevArrowBtn->handleHover(local_x, local_y, mask); + } + if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y)) + { + S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft; + S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom; + mJumpNextArrowBtn->handleHover(local_x, local_y, mask); + } + if (mPrevArrowBtn->getRect().pointInRect(x, y)) + { + S32 local_x = x - mPrevArrowBtn->getRect().mLeft; + S32 local_y = y - mPrevArrowBtn->getRect().mBottom; + mPrevArrowBtn->handleHover(local_x, local_y, mask); + } + else if (mNextArrowBtn->getRect().pointInRect(x, y)) + { + S32 local_x = x - mNextArrowBtn->getRect().mLeft; + S32 local_y = y - mNextArrowBtn->getRect().mBottom; + mNextArrowBtn->handleHover(local_x, local_y, mask); + } + } + + for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + { + LLTabTuple* tuple = *iter; + tuple->mButton->setVisible( TRUE ); + S32 local_x = x - tuple->mButton->getRect().mLeft; + S32 local_y = y - tuple->mButton->getRect().mBottom; + if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible()) + { + tuple->mButton->onCommit(); + } + } + // Stop the timer whether successful or not. Don't let it run forever. + mDragAndDropDelayTimer.stop(); } } - else + else { - // We're not on an arrow or just left it. Stop the time (in case it was running). - mDragAndDropDelayTimer.stop(); - } - } - - for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) - { - LLTabTuple* tuple = *iter; - tuple->mButton->setVisible( TRUE ); - S32 local_x = x - tuple->mButton->getRect().mLeft; - S32 local_y = y - tuple->mButton->getRect().mBottom; - if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible()) - { - tuple->mButton->onCommit(); + // Start a timer so we don't open tabs as soon as we hover on them + mDragAndDropDelayTimer.start(); } } @@ -695,12 +714,11 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag void LLTabContainer::addTabPanel(LLPanel* child, const std::string& label, BOOL select, - void (*on_tab_clicked)(void*, bool), - void* userdata, S32 indent, BOOL placeholder, eInsertionPoint insertion_point) { + if (child->getParent() == this) { // already a child of mine @@ -722,22 +740,30 @@ void LLTabContainer::addTabPanel(LLPanel* child, // Tab panel S32 tab_panel_top; S32 tab_panel_bottom; - if( getTabPosition() == LLTabContainer::TOP ) + if (!getTabsHidden()) { - S32 tab_height = mIsVertical ? BTN_HEIGHT : TABCNTR_TAB_HEIGHT; - tab_panel_top = getRect().getHeight() - getTopBorderHeight() - (tab_height - TABCNTR_BUTTON_PANEL_OVERLAP); - tab_panel_bottom = LLPANEL_BORDER_WIDTH; + if( getTabPosition() == LLTabContainer::TOP ) + { + S32 tab_height = mIsVertical ? BTN_HEIGHT : TABCNTR_TAB_HEIGHT; + tab_panel_top = getRect().getHeight() - getTopBorderHeight() - (tab_height - TABCNTR_BUTTON_PANEL_OVERLAP); + tab_panel_bottom = LLPANEL_BORDER_WIDTH; + } + else + { + tab_panel_top = getRect().getHeight() - getTopBorderHeight(); + tab_panel_bottom = (TABCNTR_TAB_HEIGHT - TABCNTR_BUTTON_PANEL_OVERLAP); // Run to the edge, covering up the border + } } else { - tab_panel_top = getRect().getHeight() - getTopBorderHeight(); - tab_panel_bottom = (TABCNTR_TAB_HEIGHT - TABCNTR_BUTTON_PANEL_OVERLAP); // Run to the edge, covering up the border + //Scip tab button space if they are invisible(EXT - 576) + tab_panel_top = getRect().getHeight(); + tab_panel_bottom = LLPANEL_BORDER_WIDTH; } - LLRect tab_panel_rect; - if (mIsVertical) + if (!getTabsHidden() && mIsVertical) { - tab_panel_rect = LLRect(mMinTabWidth + (LLPANEL_BORDER_WIDTH * 2) + TABCNTRV_PAD, + tab_panel_rect = LLRect(mMinTabWidth + mRightTabBtnOffset + (LLPANEL_BORDER_WIDTH * 2) + TABCNTRV_PAD, getRect().getHeight() - LLPANEL_BORDER_WIDTH, getRect().getWidth() - LLPANEL_BORDER_WIDTH, LLPANEL_BORDER_WIDTH); @@ -803,7 +829,7 @@ void LLTabContainer::addTabPanel(LLPanel* child, LLStringUtil::null, LLStringUtil::null, LLStringUtil::null, - &LLTabContainer::onTabBtn, NULL, + NULL, NULL, font, trimmed_label, trimmed_label); btn->setImages(std::string("tab_left.tga"), std::string("tab_left_selected.tga")); @@ -825,7 +851,7 @@ void LLTabContainer::addTabPanel(LLPanel* child, btn = new LLButton(std::string(child->getName()) + " tab", btn_rect, LLStringUtil::null, LLStringUtil::null, LLStringUtil::null, - &LLTabContainer::onTabBtn, NULL, // set userdata below + NULL, NULL, // set userdata below font, trimmed_label, trimmed_label ); btn->setVisible( FALSE ); @@ -854,24 +880,33 @@ void LLTabContainer::addTabPanel(LLPanel* child, } } - LLTabTuple* tuple = new LLTabTuple( this, child, btn, on_tab_clicked, userdata, textbox ); + LLTabTuple* tuple = new LLTabTuple( this, child, btn, textbox ); insertTuple( tuple, insertion_point ); - if (textbox) + //Don't add button and textbox if tab buttons are invisible(EXT - 576) + if (!getTabsHidden()) { - textbox->setSaveToXML(false); - addChild( textbox, 0 ); + if (textbox) + { + textbox->setSaveToXML(false); + addChild( textbox, 0 ); + } } if (btn) { btn->setSaveToXML(false); - btn->setCallbackUserData( tuple ); + btn->setClickedCallback(boost::bind(&LLTabContainer::onTabBtn, this, _2, child)); addChild( btn, 0 ); } if (child) { addChild(child, 1); } + + sendChildToFront(mPrevArrowBtn); + sendChildToFront(mNextArrowBtn); + sendChildToFront(mJumpPrevArrowBtn); + sendChildToFront(mJumpNextArrowBtn); if( select ) { @@ -883,7 +918,7 @@ void LLTabContainer::addTabPanel(LLPanel* child, void LLTabContainer::addPlaceholder(LLPanel* child, const std::string& label) { - addTabPanel(child, label, FALSE, NULL, NULL, 0, TRUE); + addTabPanel(child, label, FALSE, 0, TRUE); } void LLTabContainer::removeTabPanel(LLPanel* child) @@ -984,6 +1019,10 @@ void LLTabContainer::enableTabButton(S32 which, BOOL enable) { mTabList[which]->mButton->setEnabled(enable); } + // Stop the DaD timer as it might run forever + // enableTabButton() is typically called on refresh and draw when anything changed + // in the tab container so it's a good time to reset that. + mDragAndDropDelayTimer.stop(); } void LLTabContainer::deleteAllTabs() @@ -1154,8 +1193,8 @@ BOOL LLTabContainer::selectTabPanel(LLPanel* child) BOOL LLTabContainer::selectTab(S32 which) { - if (which >= getTabCount()) return FALSE; - if (which < 0) return FALSE; + if (which >= getTabCount() || which < 0) + return FALSE; //if( gFocusMgr.childHasKeyboardFocus( this ) ) //{ @@ -1167,28 +1206,26 @@ BOOL LLTabContainer::selectTab(S32 which) { return FALSE; } + + LLSD cbdata; + if (selected_tuple->mTabPanel) + cbdata = selected_tuple->mTabPanel->getName(); - if (!selected_tuple->mPrecommitChangeCallback) + BOOL res = FALSE; + if( !mValidateSignal || (*mValidateSignal)( this, cbdata ) ) { - return setTab(which); + res = setTab(which); + if (res && mCommitSignal) + { + (*mCommitSignal)(this, cbdata); + } } - - mNextTabIdx = which; - selected_tuple->mPrecommitChangeCallback(selected_tuple->mUserData, false); - return TRUE; + + return res; } BOOL LLTabContainer::setTab(S32 which) { - if (which == -1) - { - if (mNextTabIdx == -1) - { - return FALSE; - } - which = mNextTabIdx; - mNextTabIdx = -1; - } LLTabTuple* selected_tuple = getTab(which); if (!selected_tuple) @@ -1212,12 +1249,12 @@ BOOL LLTabContainer::setTab(S32 which) // RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs tuple->mButton->setTabStop( is_selected ); - if( is_selected && (mIsVertical || (getMaxScrollPos() > 0))) + if (is_selected) { // Make sure selected tab is within scroll region if (mIsVertical) { - S32 num_visible = getTabCount() - getMaxScrollPos(); + /*S32 num_visible = getTabCount() - getMaxScrollPos(); if( i >= getScrollPos() && i <= getScrollPos() + num_visible) { setCurrentPanelIndex(which); @@ -1226,9 +1263,28 @@ BOOL LLTabContainer::setTab(S32 which) else { is_visible = FALSE; + }*/ + if (getMaxScrollPos() > 0) + { + if( i < getScrollPos() ) + { + setScrollPos(i); + } + else + { + S32 available_height_with_arrows = getRect().getHeight() - getTopBorderHeight() - (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1); + S32 min_scroll_pos = llmax(i-llfloor(((F32)available_height_with_arrows)/((F32)BTN_HEIGHT))+1,0); + setScrollPos(llclamp(getScrollPos(), min_scroll_pos, i)); + setScrollPos(llmin(getScrollPos(), getMaxScrollPos())); + } + is_visible = TRUE; + } + else + { + is_visible = TRUE; } } - else + else if (getMaxScrollPos() > 0) { if( i < getScrollPos() ) { @@ -1259,20 +1315,20 @@ BOOL LLTabContainer::setTab(S32 which) } is_visible = TRUE; } + else + { + is_visible = TRUE; + } } i++; } - if( selected_tuple->mOnChangeCallback ) - { - selected_tuple->mOnChangeCallback( selected_tuple->mUserData, false ); - } } - if (mIsVertical && getCurrentPanelIndex() >= 0) + /*if (mIsVertical && getCurrentPanelIndex() >= 0) { LLTabTuple* tuple = getTab(getCurrentPanelIndex()); tuple->mTabPanel->setVisible( TRUE ); tuple->mButton->setToggleState( TRUE ); - } + }*/ return is_visible; } @@ -1315,28 +1371,44 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L if( tuple ) { tuple->mButton->setImageOverlay(image_name, LLFontGL::RIGHT, color); + reshapeTuple(tuple); + } +} - if (!mIsVertical) - { - const LLFontGL* fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ); - // remove current width from total tab strip width - mTotalTabWidth -= tuple->mButton->getRect().getWidth(); +void LLTabContainer::setTabImage(LLPanel* child, const LLUUID& image_id, const LLColor4& color) +{ + LLTabTuple* tuple = getTabByPanel(child); + if( tuple ) + { + tuple->mButton->setImageOverlay(image_id, LLFontGL::LEFT, color); + reshapeTuple(tuple); + } +} - S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ? - tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : - 0; +void LLTabContainer::reshapeTuple(LLTabTuple* tuple) +{ - tuple->mPadding = image_overlay_width; + if (!mIsVertical) + { + const LLFontGL* fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ); + S32 image_overlay_width = 0; + image_overlay_width = tuple->mButton->getImageOverlay().notNull() ? + tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : 0; + // remove current width from total tab strip width + mTotalTabWidth -= tuple->mButton->getRect().getWidth(); - tuple->mButton->setRightHPad(6); - tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), + + + tuple->mPadding = image_overlay_width; + + tuple->mButton->setRightHPad(6); + tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tuple->mButton->getRect().getHeight()); - // add back in button width to total tab strip width - mTotalTabWidth += tuple->mButton->getRect().getWidth(); + // add back in button width to total tab strip width + mTotalTabWidth += tuple->mButton->getRect().getWidth(); - // tabs have changed size, might need to scroll to see current tab - updateMaxScrollPos(); - } + // tabs have changed size, might need to scroll to see current tab + updateMaxScrollPos(); } } @@ -1368,33 +1440,6 @@ S32 LLTabContainer::getTopBorderHeight() const return mTopBorderHeight; } -void LLTabContainer::setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(void*, bool)) -{ - LLTabTuple* tuplep = getTabByPanel(tab); - if (tuplep) - { - tuplep->mOnChangeCallback = on_tab_clicked; - } -} - -void LLTabContainer::setTabPrecommitChangeCallback(LLPanel* tab, void (*on_precommit)(void*, bool)) -{ - LLTabTuple* tuplep = getTabByPanel(tab); - if (tuplep) - { - tuplep->mPrecommitChangeCallback = on_precommit; - } -} - -void LLTabContainer::setTabUserData(LLPanel* tab, void* userdata) -{ - LLTabTuple* tuplep = getTabByPanel(tab); - if (tuplep) - { - tuplep->mUserData = userdata; - } -} - void LLTabContainer::setRightTabBtnOffset(S32 offset) { mNextArrowBtn->translate( -offset - mRightTabBtnOffset, 0 ); @@ -1408,7 +1453,7 @@ void LLTabContainer::setPanelTitle(S32 index, const std::string& title) { LLTabTuple* tuple = getTab(index); LLButton* tab_button = tuple->mButton; - const LLFontGL* fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ); + const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall(); mTotalTabWidth -= tab_button->getRect().getWidth(); tab_button->reshape(llclamp(fontp->getWidth(title) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight()); mTotalTabWidth += tab_button->getRect().getWidth(); @@ -1419,84 +1464,62 @@ void LLTabContainer::setPanelTitle(S32 index, const std::string& title) } -// static -void LLTabContainer::onTabBtn( void* userdata ) +void LLTabContainer::onTabBtn( const LLSD& data, LLPanel* panel ) { - LLTabTuple* tuple = (LLTabTuple*) userdata; - LLTabContainer* self = tuple->mTabContainer; - self->selectTabPanel( tuple->mTabPanel ); + LLTabTuple* tuple = getTabByPanel(panel); + selectTabPanel( panel ); - tuple->mTabPanel->setFocus(TRUE); -} - -// static -void LLTabContainer::onCloseBtn( void* userdata ) -{ - LLTabContainer* self = (LLTabContainer*) userdata; - if( self->mCloseCallback ) + if (tuple) { - self->mCloseCallback( self->mCallbackUserdata ); + tuple->mTabPanel->setFocus(TRUE); } } -// static -void LLTabContainer::onNextBtn( void* userdata ) +void LLTabContainer::onNextBtn( const LLSD& data ) { - // Scroll tabs to the left - LLTabContainer* self = (LLTabContainer*) userdata; - if (!self->mScrolled) + if (!mScrolled) { - self->scrollNext(); + scrollNext(); } - self->mScrolled = FALSE; + mScrolled = FALSE; } -// static -void LLTabContainer::onNextBtnHeld( void* userdata ) +void LLTabContainer::onNextBtnHeld( const LLSD& data ) { - LLTabContainer* self = (LLTabContainer*) userdata; - if (self->mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME) + if (mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME) { - self->mScrollTimer.reset(); - self->scrollNext(); - self->mScrolled = TRUE; + mScrollTimer.reset(); + scrollNext(); + mScrolled = TRUE; } } -// static -void LLTabContainer::onPrevBtn( void* userdata ) +void LLTabContainer::onPrevBtn( const LLSD& data ) { - LLTabContainer* self = (LLTabContainer*) userdata; - if (!self->mScrolled) + if (!mScrolled) { - self->scrollPrev(); + scrollPrev(); } - self->mScrolled = FALSE; + mScrolled = FALSE; } -// static -void LLTabContainer::onJumpFirstBtn( void* userdata ) +void LLTabContainer::onJumpFirstBtn( const LLSD& data ) { - LLTabContainer* self = (LLTabContainer*) userdata; - self->mScrollPos = 0; + mScrollPos = 0; } -// static -void LLTabContainer::onJumpLastBtn( void* userdata ) +void LLTabContainer::onJumpLastBtn( const LLSD& data ) { - LLTabContainer* self = (LLTabContainer*) userdata; - self->mScrollPos = self->mMaxScrollPos; + mScrollPos = mMaxScrollPos; } -// static -void LLTabContainer::onPrevBtnHeld( void* userdata ) +void LLTabContainer::onPrevBtnHeld( const LLSD& data ) { - LLTabContainer* self = (LLTabContainer*) userdata; - if (self->mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME) + if (mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME) { - self->mScrollTimer.reset(); - self->scrollPrev(); - self->mScrolled = TRUE; + mScrollTimer.reset(); + scrollPrev(); + mScrolled = TRUE; } } @@ -1583,8 +1606,7 @@ LLView* LLTabContainer::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto } BOOL placeholder = FALSE; child->getAttributeBOOL("placeholder", placeholder); - tab_container->addTabPanel(panelp, label, false, - NULL, NULL, 0, placeholder); + tab_container->addTabPanel(panelp, label, false, 0, placeholder); } } @@ -1614,7 +1636,7 @@ void LLTabContainer::initButtons() { // Left and right scroll arrows (for when there are too many tabs to show all at once). S32 btn_top = getRect().getHeight(); - S32 btn_top_lower = getRect().mBottom+TABCNTRV_ARROW_BTN_SIZE; + S32 btn_top_lower = TABCNTRV_ARROW_BTN_SIZE; LLRect up_arrow_btn_rect; up_arrow_btn_rect.setLeftTopAndSize( mMinTabWidth/2 , btn_top, TABCNTRV_ARROW_BTN_SIZE, TABCNTRV_ARROW_BTN_SIZE ); @@ -1625,18 +1647,20 @@ void LLTabContainer::initButtons() out_id = "UIImgBtnScrollUpOutUUID"; in_id = "UIImgBtnScrollUpInUUID"; mPrevArrowBtn = new LLButton(std::string("Up Arrow"), up_arrow_btn_rect, - out_id, in_id, LLStringUtil::null, - &onPrevBtn, this, NULL ); + out_id, in_id, LLStringUtil::null, NULL ); mPrevArrowBtn->setFollowsTop(); mPrevArrowBtn->setFollowsLeft(); - + mPrevArrowBtn->setCommitCallback(boost::bind(&LLTabContainer::onPrevBtn,this,_2)); + mPrevArrowBtn->setHeldDownCallback(boost::bind(&LLTabContainer::onPrevBtnHeld, this, _2)); + out_id = "UIImgBtnScrollDownOutUUID"; in_id = "UIImgBtnScrollDownInUUID"; mNextArrowBtn = new LLButton(std::string("Down Arrow"), down_arrow_btn_rect, - out_id, in_id, LLStringUtil::null, - &onNextBtn, this, NULL ); + out_id, in_id, LLStringUtil::null, NULL ); mNextArrowBtn->setFollowsBottom(); mNextArrowBtn->setFollowsLeft(); + mNextArrowBtn->setCommitCallback(boost::bind(&LLTabContainer::onNextBtn,this,_2)); + mNextArrowBtn->setHeldDownCallback(boost::bind(&LLTabContainer::onNextBtnHeld, this, _2)); } else // Horizontal { @@ -1674,31 +1698,35 @@ void LLTabContainer::initButtons() in_id = "UIImgBtnJumpLeftInUUID"; mJumpPrevArrowBtn = new LLButton(std::string("Jump Left Arrow"), jump_left_arrow_btn_rect, out_id, in_id, LLStringUtil::null, - &LLTabContainer::onJumpFirstBtn, this, LLFontGL::getFontSansSerif() ); + NULL, NULL, LLFontGL::getFontSansSerif() ); + mJumpPrevArrowBtn->setCommitCallback(boost::bind(&LLTabContainer::onJumpFirstBtn, this, _2)); mJumpPrevArrowBtn->setFollowsLeft(); out_id = "UIImgBtnScrollLeftOutUUID"; in_id = "UIImgBtnScrollLeftInUUID"; mPrevArrowBtn = new LLButton(std::string("Left Arrow"), left_arrow_btn_rect, out_id, in_id, LLStringUtil::null, - &LLTabContainer::onPrevBtn, this, LLFontGL::getFontSansSerif() ); - mPrevArrowBtn->setHeldDownCallback(onPrevBtnHeld); + NULL, NULL, LLFontGL::getFontSansSerif() ); + + mPrevArrowBtn->setCommitCallback(boost::bind(&LLTabContainer::onPrevBtn, this, _2)); + mPrevArrowBtn->setHeldDownCallback(boost::bind(&LLTabContainer::onPrevBtnHeld, this, _2)); mPrevArrowBtn->setFollowsLeft(); out_id = "UIImgBtnJumpRightOutUUID"; in_id = "UIImgBtnJumpRightInUUID"; mJumpNextArrowBtn = new LLButton(std::string("Jump Right Arrow"), jump_right_arrow_btn_rect, out_id, in_id, LLStringUtil::null, - &LLTabContainer::onJumpLastBtn, this, - LLFontGL::getFontSansSerif()); + NULL, NULL, LLFontGL::getFontSansSerif()); + mJumpNextArrowBtn->setCommitCallback(boost::bind(&LLTabContainer::onJumpLastBtn, this, _2)); mJumpNextArrowBtn->setFollowsRight(); out_id = "UIImgBtnScrollRightOutUUID"; in_id = "UIImgBtnScrollRightInUUID"; mNextArrowBtn = new LLButton(std::string("Right Arrow"), right_arrow_btn_rect, out_id, in_id, LLStringUtil::null, - &LLTabContainer::onNextBtn, this, - LLFontGL::getFontSansSerif()); + NULL, NULL, LLFontGL::getFontSansSerif()); + mNextArrowBtn->setCommitCallback(boost::bind(&LLTabContainer::onNextBtn, this, _2)); + mNextArrowBtn->setHeldDownCallback(boost::bind(&LLTabContainer::onNextBtnHeld, this, _2)); mNextArrowBtn->setFollowsRight(); if( getTabPosition() == TOP ) @@ -1717,12 +1745,10 @@ void LLTabContainer::initButtons() } } - mPrevArrowBtn->setHeldDownCallback(onPrevBtnHeld); mPrevArrowBtn->setSaveToXML(false); mPrevArrowBtn->setTabStop(FALSE); addChild(mPrevArrowBtn); - - mNextArrowBtn->setHeldDownCallback(onNextBtnHeld); + mNextArrowBtn->setSaveToXML(false); mNextArrowBtn->setTabStop(FALSE); addChild(mNextArrowBtn); @@ -1745,7 +1771,7 @@ void LLTabContainer::initButtons() setDefaultTabGroup(1); } -LLTabContainer::LLTabTuple* LLTabContainer::getTabByPanel(LLPanel* child) +LLTabTuple* LLTabContainer::getTabByPanel(LLPanel* child) { for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { @@ -1794,11 +1820,11 @@ void LLTabContainer::updateMaxScrollPos() BOOL no_scroll = TRUE; if (mIsVertical) { - S32 tab_total_height = (BTN_HEIGHT + TABCNTRV_PAD) * getTabCount(); - S32 available_height = getRect().getHeight() - getTopBorderHeight(); + S32 tab_total_height = (BTN_HEIGHT + TABCNTRV_PAD) * getTabCount() + TABCNTRV_PAD; + S32 available_height = getRect().getHeight() - getTopBorderHeight() - 2 * LLPANEL_BORDER_WIDTH; if( tab_total_height > available_height ) { - S32 available_height_with_arrows = getRect().getHeight() - 2*(TABCNTRV_ARROW_BTN_SIZE + 3*TABCNTRV_PAD); + S32 available_height_with_arrows = getRect().getHeight() - getTopBorderHeight() - (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1); S32 additional_needed = tab_total_height - available_height_with_arrows; setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT) ) ); no_scroll = FALSE; @@ -1846,12 +1872,12 @@ void LLTabContainer::updateMaxScrollPos() void LLTabContainer::commitHoveredButton(S32 x, S32 y) { - if (hasMouseCapture()) + if (!getTabsHidden() && hasMouseCapture()) { for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { LLTabTuple* tuple = *iter; - tuple->mButton->setVisible( TRUE ); + //tuple->mButton->setVisible( TRUE ); S32 local_x = x - tuple->mButton->getRect().mLeft; S32 local_y = y - tuple->mButton->getRect().mBottom; if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible()) diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index 8117cdee9..de5a51639 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -36,6 +36,7 @@ #include "llpanel.h" #include "lltextbox.h" #include "llframetimer.h" +class LLTabTuple; extern const S32 TABCNTR_HEADER_HEIGHT; @@ -79,9 +80,7 @@ public: void addTabPanel(LLPanel* child, const std::string& label, - BOOL select = FALSE, - void (*on_tab_clicked)(void*, bool) = NULL, - void* userdata = NULL, + BOOL select = FALSE, S32 indent = 0, BOOL placeholder = FALSE, eInsertionPoint insertion_point = END); @@ -108,20 +107,16 @@ public: BOOL selectTabPanel( LLPanel* child ); BOOL selectTab(S32 which); BOOL selectTabByName(const std::string& title); - BOOL setTab(S32 which); BOOL getTabPanelFlashing(LLPanel* child); void setTabPanelFlashing(LLPanel* child, BOOL state); void setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white); + void setTabImage(LLPanel* child, const LLUUID& img_id, const LLColor4& color = LLColor4::white); void setTitle( const std::string& title ); const std::string getPanelTitle(S32 index); void setTopBorderHeight(S32 height); S32 getTopBorderHeight() const; - - void setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(void*,bool)); - void setTabPrecommitChangeCallback(LLPanel* tab, void (*on_precommit)(void*, bool)); - void setTabUserData(LLPanel* tab, void* userdata); void setRightTabBtnOffset( S32 offset ); void setPanelTitle(S32 index, const std::string& title); @@ -134,51 +129,22 @@ public: void startDragAndDropDelayTimer() { mDragAndDropDelayTimer.start(); } - static void onCloseBtn(void* userdata); - static void onTabBtn(void* userdata); - static void onNextBtn(void* userdata); - static void onNextBtnHeld(void* userdata); - static void onPrevBtn(void* userdata); - static void onPrevBtnHeld(void* userdata); - static void onJumpFirstBtn( void* userdata ); - static void onJumpLastBtn( void* userdata ); + void onTabBtn( const LLSD& data, LLPanel* panel ); + void onNextBtn(const LLSD& data); + void onNextBtnHeld(const LLSD& data); + void onPrevBtn(const LLSD& data); + void onPrevBtnHeld(const LLSD& data); + void onJumpFirstBtn( const LLSD& data ); + void onJumpLastBtn( const LLSD& data ); static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); private: - // Structure used to map tab buttons to and from tab panels - struct LLTabTuple - { - LLTabTuple( LLTabContainer* c, LLPanel* p, LLButton* b, - void (*cb)(void*,bool), void* userdata, LLTextBox* placeholder = NULL, - void (*pcb)(void*,bool) = NULL) - : - mTabContainer(c), - mTabPanel(p), - mButton(b), - mOnChangeCallback( cb ), - mPrecommitChangeCallback( pcb ), - mUserData( userdata ), - mOldState(FALSE), - mPlaceholderText(placeholder), - mPadding(0) - {} - - LLTabContainer* mTabContainer; - LLPanel* mTabPanel; - LLButton* mButton; - void (*mOnChangeCallback)(void*, bool); - void (*mPrecommitChangeCallback)(void*,bool); // Precommit callback gets called before tab is changed and - // can prevent it from being changed. onChangeCallback is called - // immediately after tab is actually changed - Nyx - void* mUserData; - BOOL mOldState; - LLTextBox* mPlaceholderText; - S32 mPadding; - }; void initButtons(); + BOOL setTab(S32 which); + LLTabTuple* getTab(S32 index) { return mTabList[index]; } LLTabTuple* getTabByPanel(LLPanel* child); void insertTuple(LLTabTuple * tuple, eInsertionPoint insertion_point); @@ -201,13 +167,13 @@ private: void updateMaxScrollPos(); void commitHoveredButton(S32 x, S32 y); + void reshapeTuple(LLTabTuple* tuple); // Variables typedef std::vector tuple_list_t; tuple_list_t mTabList; S32 mCurrentTabIdx; - S32 mNextTabIdx; BOOL mTabsHidden; BOOL mScrolled; @@ -216,9 +182,6 @@ private: S32 mScrollPosPixels; S32 mMaxScrollPos; - void (*mCloseCallback)(void*); - void* mCallbackUserdata; - LLTextBox* mTitleBox; S32 mTopBorderHeight; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index cd9d06c58..4bc9ee1fc 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -356,12 +356,12 @@ LLTextEditor::LLTextEditor( { menu = new LLMenuGL(LLStringUtil::null); }*/ - menu->append(new LLMenuItemCallGL("Cut", context_cut, NULL, this)); - menu->append(new LLMenuItemCallGL("Copy", context_copy, NULL, this)); - menu->append(new LLMenuItemCallGL("Paste", context_paste, NULL, this)); - menu->append(new LLMenuItemCallGL("Delete", context_delete, NULL, this)); - menu->append(new LLMenuItemCallGL("Select All", context_selectall, NULL, this)); - menu->appendSeparator("Spelsep"); + menu->addChild(new LLMenuItemCallGL("Cut", context_cut, NULL, this)); + menu->addChild(new LLMenuItemCallGL("Copy", context_copy, NULL, this)); + menu->addChild(new LLMenuItemCallGL("Paste", context_paste, NULL, this)); + menu->addChild(new LLMenuItemCallGL("Delete", context_delete, NULL, this)); + menu->addChild(new LLMenuItemCallGL("Select All", context_selectall, NULL, this)); + menu->addSeparator(); menu->setCanTearOff(FALSE); menu->setVisible(FALSE); mPopupMenuHandle = menu->getHandle(); @@ -372,18 +372,12 @@ LLTextEditor::~LLTextEditor() { gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() - // Route menu back to the default - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } - // Scrollbar is deleted by LLView mHoverSegment = NULL; std::for_each(mSegments.begin(), mSegments.end(), DeletePointer()); std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); - LLView::deleteViewByHandle(mPopupMenuHandle); + //LLView::deleteViewByHandle(mPopupMenuHandle); } void LLTextEditor::context_cut(void* data) { @@ -1283,7 +1277,8 @@ BOOL LLTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_ BOOL LLTextEditor::handleScrollWheel(S32 x, S32 y, S32 clicks) { // Pretend the mouse is over the scrollbar - return mScrollbar->handleScrollWheel( 0, 0, clicks ); + mScrollbar->handleScrollWheel( 0, 0, clicks ); + return TRUE; } BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) @@ -1389,7 +1384,7 @@ BOOL LLTextEditor::handleRightMouseDown( S32 x, S32 y, MASK mask ) SpellMenuBind * tempBind = suggestionMenuItems[i]; if(tempBind) { - menu->remove(tempBind->menuItem); + menu->removeChild(tempBind->menuItem); tempBind->menuItem->die(); //delete tempBind->menuItem; //tempBind->menuItem = NULL; @@ -1425,7 +1420,7 @@ BOOL LLTextEditor::handleRightMouseDown( S32 x, S32 y, MASK mask ) tempStruct->word, spell_correct, NULL, tempStruct); tempStruct->menuItem = suggMenuItem; suggestionMenuItems.push_back(tempStruct); - menu->append(suggMenuItem); + menu->addChild(suggMenuItem); } SpellMenuBind * tempStruct = new SpellMenuBind; tempStruct->origin = this; @@ -1437,7 +1432,7 @@ BOOL LLTextEditor::handleRightMouseDown( S32 x, S32 y, MASK mask ) "Add Word", spell_add, NULL, tempStruct); tempStruct->menuItem = suggMenuItem; suggestionMenuItems.push_back(tempStruct); - menu->append(suggMenuItem); + menu->addChild(suggMenuItem); } } @@ -1456,7 +1451,7 @@ BOOL LLTextEditor::handleRightMouseDown( S32 x, S32 y, MASK mask ) tempStruct->word, spell_show, NULL, tempStruct); tempStruct->menuItem = suggMenuItem; suggestionMenuItems.push_back(tempStruct); - menu->append(suggMenuItem); + menu->addChild(suggMenuItem); } mLastContextMenuX = x; mLastContextMenuY = y; @@ -3246,7 +3241,7 @@ void LLTextEditor::drawCursor() } // Make sure the IME is in the right place - LLRect screen_pos = getScreenRect(); + LLRect screen_pos = calcScreenRect(); LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_left), screen_pos.mBottom + llfloor(cursor_top) ); ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]); diff --git a/indra/llui/lltrans.cpp b/indra/llui/lltrans.cpp index eee2ddcf2..f7988c965 100644 --- a/indra/llui/lltrans.cpp +++ b/indra/llui/lltrans.cpp @@ -72,7 +72,11 @@ bool LLTrans::parseStrings(const std::string& xml_filename, const std::setgetTextContents()); + std::string contents; + //value is used for strings with preceeding spaces. If not present, fall back to getTextContents() + if(!string->getAttributeString("value",contents)) + contents=string->getTextContents(); + LLTransTemplate xml_template(string_name, contents); sStringTemplates[xml_template.mName] = xml_template; std::set::const_iterator iter = default_args.find(xml_template.mName); diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index fa1411f23..bf5fc316d 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -809,7 +809,11 @@ void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LL gGL.flush(); glLineWidth(2.5f); - glLineStipple(2, 0x3333 << shift); + if (!LLGLSLShader::sNoFixedFunction) + { + glLineStipple(2, 0x3333 << shift); + } + gGL.begin(LLRender::LINES); { @@ -1644,21 +1648,22 @@ void LLUI::translate(F32 x, F32 y, F32 z) gGL.translatef(x,y,z); LLFontGL::sCurOrigin.mX += (S32) x; LLFontGL::sCurOrigin.mY += (S32) y; - LLFontGL::sCurOrigin.mZ += z; + LLFontGL::sCurDepth += z; } //static void LLUI::pushMatrix() { gGL.pushMatrix(); - LLFontGL::sOriginStack.push_back(LLFontGL::sCurOrigin); + LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth)); } //static void LLUI::popMatrix() { gGL.popMatrix(); - LLFontGL::sCurOrigin = *LLFontGL::sOriginStack.rbegin(); + LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first; + LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second; LLFontGL::sOriginStack.pop_back(); } @@ -1668,7 +1673,7 @@ void LLUI::loadIdentity() gGL.loadIdentity(); LLFontGL::sCurOrigin.mX = 0; LLFontGL::sCurOrigin.mY = 0; - LLFontGL::sCurOrigin.mZ = 0; + LLFontGL::sCurDepth = 0.f; } //static diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 49767a547..f1e45dc11 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -42,10 +42,10 @@ static LLRegisterWidget r("ui_ctrl"); // NOTE: the LLFocusableElement implementation has been moved to llfocusmgr.cpp, to mirror the header where the class is defined. LLUICtrl::LLUICtrl() : + mViewModel(LLViewModelPtr(new LLViewModel)), mCommitSignal(NULL), mValidateSignal(NULL), mCommitCallback(NULL), - mLostTopCallback(NULL), mValidateCallback(NULL), mCallbackUserData(NULL), mTentative(FALSE), @@ -63,8 +63,8 @@ LLUICtrl::LLUICtrl(const std::string& name, const LLRect& rect, BOOL mouse_opaqu LLView( name, rect, mouse_opaque, reshape ), mCommitSignal(NULL), mValidateSignal(NULL), + mViewModel(LLViewModelPtr(new LLViewModel)), mCommitCallback( on_commit_callback), - mLostTopCallback( NULL ), mValidateCallback( NULL ), mCallbackUserData( callback_userdata ), mTentative( FALSE ), @@ -103,12 +103,33 @@ BOOL LLUICtrl::isCtrl() const return TRUE; } +//virtual +void LLUICtrl::setValue(const LLSD& value) +{ + mViewModel->setValue(value); +} + //virtual LLSD LLUICtrl::getValue() const { - return LLSD(); + return mViewModel->getValue(); } +/// When two widgets are displaying the same data (e.g. during a skin +/// change), share their ViewModel. +void LLUICtrl::shareViewModelFrom(const LLUICtrl& other) +{ + // Because mViewModel is an LLViewModelPtr, this assignment will quietly + // dispose of the previous LLViewModel -- unless it's already shared by + // somebody else. + mViewModel = other.mViewModel; +} + +//virtual +LLViewModel* LLUICtrl::getViewModel() const +{ + return mViewModel; +} // virtual BOOL LLUICtrl::setTextArg( const std::string& key, const LLStringExplicit& text ) { @@ -167,58 +188,6 @@ void LLUICtrl::setFocus(BOOL b) } } -void LLUICtrl::onFocusReceived() -{ - // trigger callbacks - LLFocusableElement::onFocusReceived(); - - // find first view in hierarchy above new focus that is a LLUICtrl - LLView* viewp = getParent(); - LLUICtrl* last_focus = dynamic_cast(gFocusMgr.getLastKeyboardFocus()); - - while (viewp && !viewp->isCtrl()) - { - viewp = viewp->getParent(); - } - - // and if it has newly gained focus, call onFocusReceived() - LLUICtrl* ctrlp = static_cast(viewp); - if (ctrlp && (!last_focus || !last_focus->hasAncestor(ctrlp))) - { - ctrlp->onFocusReceived(); - } -} - -void LLUICtrl::onFocusLost() -{ - // trigger callbacks - LLFocusableElement::onFocusLost(); - - // find first view in hierarchy above old focus that is a LLUICtrl - LLView* viewp = getParent(); - while (viewp && !viewp->isCtrl()) - { - viewp = viewp->getParent(); - } - - // and if it has just lost focus, call onFocusReceived() - LLUICtrl* ctrlp = static_cast(viewp); - // hasFocus() includes any descendants - if (ctrlp && !ctrlp->hasFocus()) - { - ctrlp->onFocusLost(); - } -} - -void LLUICtrl::onLostTop() -{ - if (mLostTopCallback) - { - mLostTopCallback(this, mCallbackUserData); - } -} - - // virtual void LLUICtrl::setTabStop( BOOL b ) { @@ -240,12 +209,13 @@ BOOL LLUICtrl::acceptsTextInput() const //virtual BOOL LLUICtrl::isDirty() const { - return FALSE; + return mViewModel->isDirty(); }; //virtual void LLUICtrl::resetDirty() { + mViewModel->resetDirty(); } // virtual @@ -532,6 +502,16 @@ LLUICtrl* LLUICtrl::getParentUICtrl() const return NULL; } +// *TODO: Deprecate; for backwards compatability only: +boost::signals2::connection LLUICtrl::setCommitCallback( boost::function cb, void* data) +{ + return setCommitCallback( boost::bind(cb, _1, data)); +} +boost::signals2::connection LLUICtrl::setValidateBeforeCommit( boost::function cb ) +{ + if (!mValidateSignal) mValidateSignal = new enable_signal_t(); + return mValidateSignal->connect(boost::bind(cb, _2)); +} // virtual void LLUICtrl::setTentative(BOOL b) { diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 519b45c0b..c8f9b4b85 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -38,11 +38,13 @@ #include "llrect.h" #include "llsd.h" +#include "llviewmodel.h" // *TODO move dependency to .cpp file class LLUICtrl : public LLView { public: + typedef boost::function commit_callback_t; typedef boost::signals2::signal commit_signal_t; typedef boost::signals2::signal enable_signal_t; @@ -56,15 +58,15 @@ public: U32 reshape=FOLLOWS_NONE); /*virtual*/ ~LLUICtrl(); + // We need this virtual so we can override it with derived versions + virtual LLViewModel* getViewModel() const; + // We shouldn't ever need to set this directly + //virtual void setViewModel(const LLViewModelPtr&); // LLView interface /*virtual*/ void initFromXML(LLXMLNodePtr node, LLView* parent); /*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const; /*virtual*/ BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); - /*virtual*/ void onFocusReceived(); - /*virtual*/ void onFocusLost(); /*virtual*/ BOOL isCtrl() const; - /*virtual*/ void setTentative(BOOL b); - /*virtual*/ BOOL getTentative() const; // From LLFocusableElement /*virtual*/ void setFocus( BOOL b ); @@ -77,7 +79,14 @@ public: virtual class LLCtrlListInterface* getListInterface(); virtual class LLCtrlScrollInterface* getScrollInterface(); + virtual void setTentative(BOOL b); + virtual BOOL getTentative() const; + virtual void setValue(const LLSD& value); virtual LLSD getValue() const; + /// When two widgets are displaying the same data (e.g. during a skin + /// change), share their ViewModel. + virtual void shareViewModelFrom(const LLUICtrl& other); + virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text ); virtual void setIsChrome(BOOL is_chrome); @@ -89,7 +98,6 @@ public: virtual void resetDirty(); //Defaults to no-op // Call appropriate callbacks - virtual void onLostTop(); // called when registered as top ctrl and user clicks elsewhere virtual void onCommit(); // Default to no-op: @@ -125,7 +133,9 @@ public: void setCommitCallback( void (*cb)(LLUICtrl*, void*) ) { mCommitCallback = cb; } void setValidateBeforeCommit( BOOL(*cb)(LLUICtrl*, void*) ) { mValidateCallback = cb; } - void setLostTopCallback( void (*cb)(LLUICtrl*, void*) ) { mLostTopCallback = cb; } + // *TODO: Deprecate; for backwards compatability only: + boost::signals2::connection setCommitCallback( boost::function cb, void* data); + boost::signals2::connection setValidateBeforeCommit( boost::function cb ); static LLView* fromXML(LLXMLNodePtr node, LLView* parent, class LLUICtrlFactory* factory); @@ -143,8 +153,9 @@ protected: commit_signal_t* mCommitSignal; enable_signal_t* mValidateSignal; + + LLViewModelPtr mViewModel; void (*mCommitCallback)( LLUICtrl* ctrl, void* userdata ); - void (*mLostTopCallback)( LLUICtrl* ctrl, void* userdata ); BOOL (*mValidateCallback)( LLUICtrl* ctrl, void* userdata ); void* mCallbackUserData; diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 2ecf6fc36..24a13d36e 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -228,7 +228,7 @@ bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNo bool LLUICtrlFactory::getLayeredXMLNodeFromBuffer(const std::string &buffer, LLXMLNodePtr& root) { - if (!LLXMLNode::parseBuffer(buffer.data(), buffer.size(), root, 0)) { + if (!LLXMLNode::parseBuffer((U8*)buffer.data(), buffer.size(), root, 0)) { llwarns << "Error reading UI description from buffer." << llendl; return false; } @@ -455,9 +455,11 @@ LLPieMenu *LLUICtrlFactory::buildPieMenu(const std::string &filename, LLView* pa //----------------------------------------------------------------------------- void LLUICtrlFactory::rebuild() { + built_panel_t built_panels = mBuiltPanels; + mBuiltPanels.clear(); built_panel_t::iterator built_panel_it; - for (built_panel_it = mBuiltPanels.begin(); - built_panel_it != mBuiltPanels.end(); + for (built_panel_it = built_panels.begin(); + built_panel_it != built_panels.end(); ++built_panel_it) { std::string filename = built_panel_it->second; diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index ef3a97be5..4dd0cdd73 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -38,6 +38,7 @@ #include "llcallbackmap.h" #include "llfloater.h" +#include "llinitparam.h" class LLView; class LLPanel; @@ -62,6 +63,8 @@ public: void removePanel(LLPanel* panelp) { mBuiltPanels.erase(panelp->getHandle()); } void removeFloater(LLFloater* floaterp) { mBuiltFloaters.erase(floaterp->getHandle()); } + + bool builtPanel(LLPanel* panelp) {return mBuiltPanels.find(panelp->getHandle()) != mBuiltPanels.end();} class LLMenuGL *buildMenu(const std::string &filename, LLView* parentp); class LLPieMenu *buildPieMenu(const std::string &filename, LLView* parentp); diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 68616dc12..c476e25d3 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -79,74 +79,101 @@ LLView* LLView::sEditingUIView = NULL; S32 LLView::sLastLeftXML = S32_MIN; S32 LLView::sLastBottomXML = S32_MIN; +LLView::DrilldownFunc LLView::sDrilldown = + boost::bind(&LLView::pointInView, _1, _2, _3, HIT_TEST_USE_BOUNDING_RECT); + #if LL_DEBUG BOOL LLView::sIsDrawing = FALSE; #endif -LLView::LLView() : - mParentView(NULL), - mReshapeFlags(FOLLOWS_NONE), - mDefaultTabGroup(0), - mEnabled(TRUE), - mMouseOpaque(TRUE), - mSoundFlags(MOUSE_UP), // default to only make sound on mouse up - mSaveToXML(TRUE), - mIsFocusRoot(FALSE), - mLastVisible(TRUE), - mUseBoundingRect(FALSE), - mVisible(TRUE), - mNextInsertionOrdinal(0), - mHoverCursor(UI_CURSOR_ARROW), - // - mDelayedDelete(FALSE) - // +LLView::Follows::Follows() +: string(""), + flags("flags", FOLLOWS_NONE) +{} + +LLView::Params::Params() +: name("name", std::string("unnamed")), + enabled("enabled", true), + visible("visible", true), + mouse_opaque("mouse_opaque", true), + follows("follows"), + hover_cursor("hover_cursor", "UI_CURSOR_ARROW"), + use_bounding_rect("use_bounding_rect", false), + tab_group("tab_group", 0), + default_tab_group("default_tab_group"), + //tool_tip("tool_tip"), + sound_flags("sound_flags", MOUSE_UP), + layout("layout"), + rect("rect"), + bottom_delta("bottom_delta", S32_MAX), + top_pad("top_pad"), + top_delta("top_delta", S32_MAX), + left_pad("left_pad"), + left_delta("left_delta", S32_MAX), + from_xui("from_xui", true), + focus_root("focus_root", false), + needs_translate("translate"), + xmlns("xmlns"), + xmlns_xsi("xmlns:xsi"), + xsi_schemaLocation("xsi:schemaLocation"), + xsi_type("xsi:type") + { + addSynonym(rect, ""); } -LLView::LLView(const std::string& name, BOOL mouse_opaque) : - mParentView(NULL), - mName(name), - mReshapeFlags(FOLLOWS_NONE), - mDefaultTabGroup(0), - mEnabled(TRUE), - mMouseOpaque(mouse_opaque), - mSoundFlags(MOUSE_UP), // default to only make sound on mouse up - mSaveToXML(TRUE), - mIsFocusRoot(FALSE), - mLastVisible(TRUE), - mUseBoundingRect(FALSE), - mVisible(TRUE), - mNextInsertionOrdinal(0), - mHoverCursor(UI_CURSOR_ARROW), - // - mDelayedDelete(FALSE) - // +LLView::LLView(const LLView::Params& p) { + init(p); } - -LLView::LLView( - const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 reshape) : - mParentView(NULL), - mName(name), - mRect(rect), - mBoundingRect(rect), - mReshapeFlags(reshape), - mDefaultTabGroup(0), - mEnabled(TRUE), - mMouseOpaque(mouse_opaque), - mSoundFlags(MOUSE_UP), // default to only make sound on mouse up - mSaveToXML(TRUE), - mIsFocusRoot(FALSE), - mLastVisible(TRUE), - mUseBoundingRect(FALSE), - mVisible(TRUE), - mNextInsertionOrdinal(0), - mHoverCursor(UI_CURSOR_ARROW), - // - mDelayedDelete(FALSE) - // +void LLView::init(const LLView::Params& p) { + mVisible = p.visible; + mInDraw = false; + mName = p.name; + mParentView = NULL; + mReshapeFlags = FOLLOWS_NONE; + mSaveToXML = p.from_xui; + mIsFocusRoot = p.focus_root; + mLastVisible = FALSE; + mNextInsertionOrdinal = 0; + mHoverCursor = getCursorFromString(p.hover_cursor); + mEnabled = p.enabled; + mMouseOpaque = p.mouse_opaque; + mSoundFlags = p.sound_flags; + mUseBoundingRect = p.use_bounding_rect; + mDefaultTabGroup = p.default_tab_group; + mLastTabGroup = 0; + //mToolTipMsg((LLStringExplicit)p.tool_tip()), + //mDefaultWidgets(NULL) + + // create rect first, as this will supply initial follows flags + setShape(p.rect); + mReshapeFlags = p.follows.flags; +} + +LLView::LLView() +{ + init(LLView::Params()); +} + +LLView::LLView(const std::string& name, BOOL mouse_opaque) +{ + LLView::Params p; + p.name = name; + p.mouse_opaque = mouse_opaque; + init(p); +} + +LLView::LLView( const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 reshape) +{ + LLView::Params p; + p.name = name; + p.mouse_opaque = mouse_opaque; + p.rect = rect; + p.follows.flags = reshape; + init(p); } @@ -154,15 +181,10 @@ LLView::~LLView() { //llinfos << "Deleting view " << mName << ":" << (void*) this << llendl; // llassert(LLView::sIsDrawing == FALSE); - if( gFocusMgr.getKeyboardFocus() == this ) - { - llwarns << "View holding keyboard focus deleted: " << getName() << ". Keyboard focus removed." << llendl; - gFocusMgr.removeKeyboardFocusWithoutCallback( this ); - } if( hasMouseCapture() ) { - llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl; + //llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl; gFocusMgr.removeMouseCaptureWithoutCallback( this ); } @@ -236,7 +258,7 @@ void LLView::setUseBoundingRect( BOOL use_bounding_rect ) } } -BOOL LLView::getUseBoundingRect() +BOOL LLView::getUseBoundingRect() const { return mUseBoundingRect; } @@ -265,6 +287,7 @@ void LLView::sendChildToFront(LLView* child) void LLView::sendChildToBack(LLView* child) { +// llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs if (child && child->getParent() == this) { // minor optimization, but more importantly, @@ -293,16 +316,18 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child) } } -void LLView::addChild(LLView* child, S32 tab_group) +// virtual +bool LLView::addChild(LLView* child, S32 tab_group) { if (!child) { - return; + return false; } if (mParentView == child) { llerrs << "Adding view " << child->getName() << " as child of itself" << llendl; } + // remove from current parent if (child->mParentView) { @@ -315,86 +340,57 @@ void LLView::addChild(LLView* child, S32 tab_group) // add to ctrl list if is LLUICtrl if (child->isCtrl()) { - // controls are stored in reverse order from render order - addCtrlAtEnd((LLUICtrl*) child, tab_group); + LLUICtrl* ctrl = static_cast(child); + mCtrlOrder.insert(tab_order_pair_t(ctrl, + tab_order_t(tab_group, mNextInsertionOrdinal))); + + mNextInsertionOrdinal++; } child->mParentView = this; updateBoundingRect(); + mLastTabGroup = tab_group; + return true; } -void LLView::addChildAtEnd(LLView* child, S32 tab_group) +bool LLView::addChildInBack(LLView* child, S32 tab_group) { - if (mParentView == child) + if(addChild(child, tab_group)) { - llerrs << "Adding view " << child->getName() << " as child of itself" << llendl; - } - // remove from current parent - if (child->mParentView) - { - child->mParentView->removeChild(child); + sendChildToBack(child); + return true; } - // add to back of child list - mChildList.push_back(child); - - // add to ctrl list if is LLUICtrl - if (child->isCtrl()) - { - // controls are stored in reverse order from render order - addCtrl((LLUICtrl*) child, tab_group); - } - - child->mParentView = this; - updateBoundingRect(); + return false; } // remove the specified child from the view, and set it's parent to NULL. -void LLView::removeChild(LLView* child, BOOL deleteIt) +void LLView::removeChild(LLView* child) { + //llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs if (child->mParentView == this) { + // if we are removing an item we are currently iterating over, that would be bad + llassert(child->mInDraw == false); mChildList.remove( child ); child->mParentView = NULL; if (child->isCtrl()) { - removeCtrl((LLUICtrl*)child); - } - if (deleteIt) - { - delete child; + child_tab_order_t::iterator found = mCtrlOrder.find(static_cast(child)); + if(found != mCtrlOrder.end()) + { + mCtrlOrder.erase(found); + } } } else { - llerrs << "LLView::removeChild called with non-child" << llendl; + llwarns << child->getName() << "is not a child of " << getName() << llendl; } updateBoundingRect(); } -void LLView::addCtrlAtEnd(LLUICtrl* ctrl, S32 tab_group) -{ - mCtrlOrder.insert(tab_order_pair_t(ctrl, - tab_order_t(tab_group, mNextInsertionOrdinal++))); -} - -void LLView::addCtrl( LLUICtrl* ctrl, S32 tab_group) -{ - // add to front of list by using negative ordinal, which monotonically increases - mCtrlOrder.insert(tab_order_pair_t(ctrl, - tab_order_t(tab_group, -1 * mNextInsertionOrdinal++))); -} - -void LLView::removeCtrl(LLUICtrl* ctrl) -{ - child_tab_order_t::iterator found = mCtrlOrder.find(ctrl); - if(found != mCtrlOrder.end()) - { - mCtrlOrder.erase(found); - } -} - LLView::ctrl_list_t LLView::getCtrlList() const { ctrl_list_t controls; @@ -511,16 +507,6 @@ LLRect LLView::getRequiredRect() return mRect; } -//virtual -void LLView::onFocusLost() -{ -} - -//virtual -void LLView::onFocusReceived() -{ -} - BOOL LLView::focusNextRoot() { LLView::child_list_t result = LLView::getFocusRootsQuery().run(this); @@ -636,11 +622,6 @@ void LLView::setVisible(BOOL visible) { if ( mVisible != visible ) { - if( !visible && (gFocusMgr.getTopCtrl() == this) ) - { - gFocusMgr.setTopCtrl( NULL ); - } - mVisible = visible; // notify children of visibility change if root, or part of visible hierarchy @@ -686,18 +667,10 @@ void LLView::setSnappedTo(const LLView* snap_view) BOOL LLView::handleHover(S32 x, S32 y, MASK mask) { - BOOL handled = childrenHandleHover( x, y, mask ) != NULL; - if( !handled - && blockMouseEvent(x, y) ) - { - LLUI::sWindow->setCursor(mHoverCursor); - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; - handled = TRUE; - } - - return handled; + return childrenHandleHover( x, y, mask ) != NULL; } + std::string LLView::getShowNamesToolTip() { LLView* view = getParent(); @@ -726,7 +699,6 @@ std::string LLView::getShowNamesToolTip() return "/" + tool_tip; } - BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) { BOOL handled = FALSE; @@ -789,6 +761,128 @@ BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_s return handled; } +bool LLView::visibleAndContains(S32 local_x, S32 local_y) +{ + return sDrilldown(this, local_x, local_y) + && getVisible(); +} + +bool LLView::visibleEnabledAndContains(S32 local_x, S32 local_y) +{ + return visibleAndContains(local_x, local_y) + && getEnabled(); +} + +void LLView::logMouseEvent() +{ + if (sDebugMouseHandling) + { + sMouseHandlerMessage = std::string("/") + mName + sMouseHandlerMessage; + } +} + +template +LLView* LLView::childrenHandleCharEvent(const std::string& desc, const METHOD& method, + CHARTYPE c, MASK mask) +{ + if ( getVisible() && getEnabled() ) + { + BOOST_FOREACH(LLView* viewp, mChildList) + { + if ((viewp->*method)(c, mask, TRUE)) + { + if (LLView::sDebugKeys) + { + llinfos << desc << " handled by " << viewp->getName() << llendl; + } + return viewp; + } + } + } + return NULL; +} + +// XDATA might be MASK, or S32 clicks +template +LLView* LLView::childrenHandleMouseEvent(const METHOD& method, S32 x, S32 y, XDATA extra, bool allow_mouse_block) +{ + BOOST_FOREACH(LLView* viewp, mChildList) + { + S32 local_x = x - viewp->getRect().mLeft; + S32 local_y = y - viewp->getRect().mBottom; + + if (!viewp->visibleEnabledAndContains(local_x, local_y)) + { + continue; + } + + if ((viewp->*method)( local_x, local_y, extra ) + || (allow_mouse_block && viewp->blockMouseEvent( local_x, local_y ))) + { + viewp->logMouseEvent(); + return viewp; + } + } + return NULL; +} + +LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + // default to not accepting drag and drop, will be overridden by handler + *accept = ACCEPT_NO; + + BOOST_FOREACH(LLView* viewp, mChildList) + { + S32 local_x = x - viewp->getRect().mLeft; + S32 local_y = y - viewp->getRect().mBottom; + if( !viewp->visibleEnabledAndContains(local_x, local_y)) + { + continue; + } + + // Differs from childrenHandleMouseEvent() simply in that this virtual + // method call diverges pretty radically from the usual (x, y, int). + if (viewp->handleDragAndDrop(local_x, local_y, mask, drop, + cargo_type, + cargo_data, + accept, + tooltip_msg) + || viewp->blockMouseEvent(local_x, local_y)) + { + return viewp; + } + } + return NULL; +} + +LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask) +{ + BOOST_FOREACH(LLView* viewp, mChildList) + { + S32 local_x = x - viewp->getRect().mLeft; + S32 local_y = y - viewp->getRect().mBottom; + if(!viewp->visibleEnabledAndContains(local_x, local_y)) + { + continue; + } + + // This call differentiates this method from childrenHandleMouseEvent(). + LLUI::sWindow->setCursor(viewp->getHoverCursor()); + + if (viewp->handleHover(local_x, local_y, mask) + || viewp->blockMouseEvent(local_x, local_y)) + { + viewp->logMouseEvent(); + return viewp; + } + } + return NULL; +} BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent) { BOOL handled = FALSE; @@ -869,53 +963,7 @@ BOOL LLView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* accept, std::string& tooltip_msg) { - // CRO this is an experiment to allow drag and drop into object inventory based on the DragAndDrop tool's permissions rather than the parent - BOOL handled = childrenHandleDragAndDrop( x, y, mask, drop, - cargo_type, - cargo_data, - accept, - tooltip_msg) != NULL; - if( !handled && blockMouseEvent(x, y) ) - { - *accept = ACCEPT_NO; - handled = TRUE; - lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLView " << getName() << llendl; - } - - return handled; -} - -LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - LLView* handled_view = FALSE; - // CRO this is an experiment to allow drag and drop into object inventory based on the DragAndDrop tool's permissions rather than the parent - if( getVisible() ) -// if( getVisible() && getEnabled() ) - { - BOOST_FOREACH(LLView* viewp, mChildList) - { - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if( viewp->pointInView(local_x, local_y) && - viewp->getVisible() && - viewp->getEnabled() && - viewp->handleDragAndDrop(local_x, local_y, mask, drop, - cargo_type, - cargo_data, - accept, - tooltip_msg)) - { - handled_view = viewp; - break; - } - } - } - return handled_view; + return childrenHandleDragAndDrop( x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL; } void LLView::onMouseCaptureLost() @@ -929,23 +977,12 @@ BOOL LLView::hasMouseCapture() BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask) { - BOOL handled = childrenHandleMouseUp( x, y, mask ) != NULL; - if( !handled && blockMouseEvent(x, y) ) - { - handled = TRUE; - } - return handled; + return childrenHandleMouseUp( x, y, mask ) != NULL; } BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask) { LLView* handled_view = childrenHandleMouseDown( x, y, mask ); - BOOL handled = (handled_view != NULL); - if( !handled && blockMouseEvent(x, y) ) - { - handled = TRUE; - handled_view = this; - } // HACK If we're editing UI, select the leaf view that ate the click. if (sEditingUI && handled_view) @@ -964,339 +1001,85 @@ BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask) } } - return handled; + return handled_view != NULL; } BOOL LLView::handleDoubleClick(S32 x, S32 y, MASK mask) { - BOOL handled = childrenHandleDoubleClick( x, y, mask ) != NULL; - if( !handled && blockMouseEvent(x, y) ) - { - handleMouseDown(x, y, mask); - handled = TRUE; - } - return handled; + return childrenHandleDoubleClick( x, y, mask ) != NULL; } BOOL LLView::handleScrollWheel(S32 x, S32 y, S32 clicks) { - BOOL handled = FALSE; - if( getVisible() && getEnabled() ) - { - handled = childrenHandleScrollWheel( x, y, clicks ) != NULL; - if( !handled && blockMouseEvent(x, y) ) - { - handled = TRUE; - } - } - return handled; + return childrenHandleScrollWheel( x, y, clicks ) != NULL; } BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; - if( !handled && blockMouseEvent(x, y) ) - { - handled = TRUE; - } - return handled; + return childrenHandleRightMouseDown( x, y, mask ) != NULL; } BOOL LLView::handleRightMouseUp(S32 x, S32 y, MASK mask) { - BOOL handled = childrenHandleRightMouseUp( x, y, mask ) != NULL; - if( !handled && blockMouseEvent(x, y) ) - { - handled = TRUE; - } - return handled; + return childrenHandleRightMouseUp( x, y, mask ) != NULL; } BOOL LLView::handleMiddleMouseDown(S32 x, S32 y, MASK mask) { - LLView* handled_view = childrenHandleMiddleMouseDown( x, y, mask ); - BOOL handled = (handled_view != NULL); - if( !handled && blockMouseEvent(x, y) ) - { - handled = TRUE; - handled_view = this; - } - - return handled; + return childrenHandleMiddleMouseDown( x, y, mask ) != NULL; } BOOL LLView::handleMiddleMouseUp(S32 x, S32 y, MASK mask) { - BOOL handled = childrenHandleMiddleMouseUp( x, y, mask ) != NULL; - if( !handled && blockMouseEvent(x, y) ) - { - handled = TRUE; - } - return handled; + return childrenHandleMiddleMouseUp( x, y, mask ) != NULL; } - LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks) { - LLView* handled_view = NULL; - if (getVisible() && getEnabled() ) - { - BOOST_FOREACH(LLView* viewp, mChildList) - { - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if (viewp->pointInView(local_x, local_y) - && viewp->getVisible() - && viewp->getEnabled() - && viewp->handleScrollWheel( local_x, local_y, clicks )) - { - if (sDebugMouseHandling) - { - sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage; - } - - handled_view = viewp; - break; - } - } - } - return handled_view; -} - -LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask) -{ - LLView* handled_view = NULL; - if (getVisible() && getEnabled() ) - { - BOOST_FOREACH(LLView* viewp, mChildList) - { - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if(viewp->pointInView(local_x, local_y) && - viewp->getVisible() && - viewp->getEnabled() && - viewp->handleHover(local_x, local_y, mask) ) - { - if (sDebugMouseHandling) - { - sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage; - } - - handled_view = viewp; - break; - } - } - } - return handled_view; + return childrenHandleMouseEvent(&LLView::handleScrollWheel, x, y, clicks, false); } // Called during downward traversal LLView* LLView::childrenHandleKey(KEY key, MASK mask) { - LLView* handled_view = NULL; - - if ( getVisible() && getEnabled() ) - { - BOOST_FOREACH(LLView* viewp, mChildList) - { - if (viewp->handleKey(key, mask, TRUE)) - { - if (LLView::sDebugKeys) - { - llinfos << "Key handled by " << viewp->getName() << llendl; - } - handled_view = viewp; - break; - } - } - } - - return handled_view; + return childrenHandleCharEvent("Key", &LLView::handleKey, key, mask); } // Called during downward traversal LLView* LLView::childrenHandleUnicodeChar(llwchar uni_char) { - LLView* handled_view = NULL; - - if ( getVisible() && getEnabled() ) - { - BOOST_FOREACH(LLView* viewp, mChildList) - { - if (viewp->handleUnicodeChar(uni_char, TRUE)) - { - if (LLView::sDebugKeys) - { - llinfos << "Unicode character handled by " << viewp->getName() << llendl; - } - handled_view = viewp; - break; - } - } - } - - return handled_view; + return childrenHandleCharEvent("Unicode character", &LLView::handleUnicodeCharWithDummyMask, + uni_char, MASK_NONE); } LLView* LLView::childrenHandleMouseDown(S32 x, S32 y, MASK mask) { - LLView* handled_view = NULL; - - BOOST_FOREACH(LLView* viewp, mChildList) - { - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - - if (viewp->pointInView(local_x, local_y) && - viewp->getVisible() && - viewp->getEnabled() && - viewp->handleMouseDown( local_x, local_y, mask )) - { - if (sDebugMouseHandling) - { - sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage; - } - handled_view = viewp; - break; - } - } - return handled_view; + return childrenHandleMouseEvent(&LLView::handleMouseDown, x, y, mask); } LLView* LLView::childrenHandleRightMouseDown(S32 x, S32 y, MASK mask) { - LLView* handled_view = NULL; - - if (getVisible() && getEnabled() ) - { - BOOST_FOREACH(LLView* viewp, mChildList) - { - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if (viewp->pointInView(local_x, local_y) && - viewp->getVisible() && - viewp->getEnabled() && - viewp->handleRightMouseDown( local_x, local_y, mask )) - { - if (sDebugMouseHandling) - { - sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage; - } - handled_view = viewp; - break; - } - } - } - return handled_view; + return childrenHandleMouseEvent(&LLView::handleRightMouseDown, x, y, mask); } LLView* LLView::childrenHandleMiddleMouseDown(S32 x, S32 y, MASK mask) { - LLView* handled_view = NULL; - - if (getVisible() && getEnabled() ) - { - BOOST_FOREACH(LLView* viewp, mChildList) - { - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if (viewp->pointInView(local_x, local_y) && - viewp->getVisible() && - viewp->getEnabled() && - viewp->handleMiddleMouseDown( local_x, local_y, mask )) - { - if (sDebugMouseHandling) - { - sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage; - } - handled_view = viewp; - break; - } - } - } - return handled_view; + return childrenHandleMouseEvent(&LLView::handleMiddleMouseDown, x, y, mask); } LLView* LLView::childrenHandleDoubleClick(S32 x, S32 y, MASK mask) { - LLView* handled_view = NULL; - - if (getVisible() && getEnabled() ) - { - BOOST_FOREACH(LLView* viewp, mChildList) - { - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if (viewp->pointInView(local_x, local_y) && - viewp->getVisible() && - viewp->getEnabled() && - viewp->handleDoubleClick( local_x, local_y, mask )) - { - if (sDebugMouseHandling) - { - sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage; - } - handled_view = viewp; - break; - } - } - } - return handled_view; + return childrenHandleMouseEvent(&LLView::handleDoubleClick, x, y, mask); } LLView* LLView::childrenHandleMouseUp(S32 x, S32 y, MASK mask) { - LLView* handled_view = NULL; - if( getVisible() && getEnabled() ) - { - BOOST_FOREACH(LLView* viewp, mChildList) - { - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if (!viewp->pointInView(local_x, local_y)) - continue; - if (!viewp->getVisible()) - continue; - if (!viewp->getEnabled()) - continue; - if (viewp->handleMouseUp( local_x, local_y, mask )) - { - if (sDebugMouseHandling) - { - sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage; - } - handled_view = viewp; - break; - } - } - } - return handled_view; + return childrenHandleMouseEvent(&LLView::handleMouseUp, x, y, mask); } LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask) { - LLView* handled_view = NULL; - if( getVisible() && getEnabled() ) - { - BOOST_FOREACH(LLView* viewp, mChildList) - { - S32 local_x = x - viewp->getRect().mLeft; - S32 local_y = y - viewp->getRect().mBottom; - if (viewp->pointInView(local_x, local_y) && - viewp->getVisible() && - viewp->getEnabled() && - viewp->handleRightMouseUp( local_x, local_y, mask )) - { - if (sDebugMouseHandling) - { - sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage; - } - handled_view = viewp; - break; - } - } - } - return handled_view; + return childrenHandleMouseEvent(&LLView::handleRightMouseUp, x, y, mask); } LLView* LLView::childrenHandleMiddleMouseUp(S32 x, S32 y, MASK mask) @@ -1327,56 +1110,72 @@ LLView* LLView::childrenHandleMiddleMouseUp(S32 x, S32 y, MASK mask) void LLView::draw() { - if (sDebugRects) - { - drawDebugRect(); + drawChildren(); +} - // Check for bogus rectangle - if (getRect().mRight <= getRect().mLeft - || getRect().mTop <= getRect().mBottom) - { - llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl; - } - } - - LLRect rootRect = getRootView()->getRect(); - LLRect screenRect; +void LLView::drawChildren() +{ // draw focused control on top of everything else - LLUICtrl* focus_view = dynamic_cast(gFocusMgr.getKeyboardFocus()); + /*LLUICtrl* focus_view = dynamic_cast(gFocusMgr.getKeyboardFocus()); if (focus_view && focus_view->getParent() != this) { focus_view = NULL; - } - - ++sDepth; - for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter) + }*/ + if (!mChildList.empty()) { - LLView *viewp = *child_iter; + LLView* rootp = getRootView(); + ++sDepth; - if (viewp->getVisible() && viewp != focus_view && viewp->getRect().isValid()) + for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend();) // ++child_iter) { - // Only draw views that are within the root view - localRectToScreen(viewp->getRect(),&screenRect); - if ( rootRect.overlaps(screenRect) ) - { - gGL.matrixMode(LLRender::MM_MODELVIEW); - LLUI::pushMatrix(); + child_list_reverse_iter_t child = child_iter++; + LLView *viewp = *child; + + if (viewp == NULL) { - LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f); - viewp->draw(); + continue; + } + + + if (viewp->getVisible() && /*viewp != focus_view && */viewp->getRect().isValid()) + { + // Only draw views that are within the root view + LLRect screen_rect = viewp->calcScreenRect(); + if ( rootp->getLocalRect().overlaps(screen_rect) ) + { + //gGL.matrixMode(LLRender::MM_MODELVIEW); + LLUI::pushMatrix(); + { + LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f); + // flag the fact we are in draw here, in case overridden draw() method attempts to remove this widget + viewp->mInDraw = true; + viewp->draw(); + viewp->mInDraw = false; + + if (sDebugRects) + { + viewp->drawDebugRect(); + + // Check for bogus rectangle + if (!getRect().isValid()) + { + llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl; + } + } + } + LLUI::popMatrix(); } - LLUI::popMatrix(); } + } - + --sDepth; } - --sDepth; - if (focus_view && focus_view->getVisible()) + /*if (focus_view && focus_view->getVisible()) { drawChild(focus_view); - } + }*/ // HACK if (sEditingUI && this == sEditingUIView) @@ -1393,12 +1192,12 @@ void LLView::drawDebugRect() // drawing solids requires texturing be disabled gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (mUseBoundingRect) + if (getUseBoundingRect()) { LLUI::translate((F32)mBoundingRect.mLeft - (F32)mRect.mLeft, (F32)mBoundingRect.mBottom - (F32)mRect.mBottom, 0.f); } - LLRect debug_rect = mUseBoundingRect ? mBoundingRect : mRect; + LLRect debug_rect = getUseBoundingRect() ? mBoundingRect : mRect; // draw red rectangle for the border LLColor4 border_color(0.f, 0.f, 0.f, 1.f); @@ -1541,43 +1340,51 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent) updateBoundingRect(); } -void LLView::updateBoundingRect() +LLRect LLView::calcBoundingRect() { - if (isDead()) return; - - if (mUseBoundingRect) - { - LLRect local_bounding_rect = LLRect::null; + LLRect local_bounding_rect = LLRect::null; BOOST_FOREACH(LLView* childp, mChildList) { // ignore invisible and "top" children when calculating bounding rect - // such as combobox popups - if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl()) - { - continue; - } - - LLRect child_bounding_rect = childp->getBoundingRect(); - - if (local_bounding_rect.isEmpty()) - { - // start out with bounding rect equal to first visible child's bounding rect - local_bounding_rect = child_bounding_rect; - } - else - { - // accumulate non-null children rectangles - if (child_bounding_rect.notEmpty()) - { - local_bounding_rect.unionWith(child_bounding_rect); - } - } + // such as combobox popups + if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl()) + { + continue; } - mBoundingRect = local_bounding_rect; - // translate into parent-relative coordinates - mBoundingRect.translate(mRect.mLeft, mRect.mBottom); + LLRect child_bounding_rect = childp->getBoundingRect(); + + if (local_bounding_rect.isEmpty()) + { + // start out with bounding rect equal to first visible child's bounding rect + local_bounding_rect = child_bounding_rect; + } + else + { + // accumulate non-null children rectangles + if (!child_bounding_rect.isEmpty()) + { + local_bounding_rect.unionWith(child_bounding_rect); + } + } + } + + // convert to parent-relative coordinates + local_bounding_rect.translate(mRect.mLeft, mRect.mBottom); + return local_bounding_rect; +} + + +void LLView::updateBoundingRect() +{ + if (isDead()) return; + + LLRect cur_rect = mBoundingRect; + + if (getUseBoundingRect()) + { + mBoundingRect = calcBoundingRect(); } else { @@ -1585,21 +1392,40 @@ void LLView::updateBoundingRect() } // give parent view a chance to resize, in case we just moved, for example - if (getParent() && getParent()->mUseBoundingRect) + if (getParent() && getParent()->getUseBoundingRect()) { getParent()->updateBoundingRect(); } + + /*if (mBoundingRect != cur_rect) + { + dirtyRect(); + }*/ + } -LLRect LLView::getScreenRect() const +LLRect LLView::calcScreenRect() const { - // *FIX: check for one-off error LLRect screen_rect; localPointToScreen(0, 0, &screen_rect.mLeft, &screen_rect.mBottom); localPointToScreen(getRect().getWidth(), getRect().getHeight(), &screen_rect.mRight, &screen_rect.mTop); return screen_rect; } +LLRect LLView::calcScreenBoundingRect() const +{ + LLRect screen_rect; + // get bounding rect, if used + LLRect bounding_rect = getUseBoundingRect() ? mBoundingRect : mRect; + + // convert to local coordinates, as defined by mRect + bounding_rect.translate(-mRect.mLeft, -mRect.mBottom); + + localPointToScreen(bounding_rect.mLeft, bounding_rect.mBottom, &screen_rect.mLeft, &screen_rect.mBottom); + localPointToScreen(bounding_rect.mRight, bounding_rect.mTop, &screen_rect.mRight, &screen_rect.mTop); + return screen_rect; +} + LLRect LLView::getLocalBoundingRect() const { LLRect local_bounding_rect = getBoundingRect(); @@ -1646,15 +1472,19 @@ BOOL LLView::hasAncestor(const LLView* parentp) const BOOL LLView::childHasKeyboardFocus( const std::string& childname ) const { - LLView *child = getChildView(childname, TRUE, FALSE); - if (child) + LLView *focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); + + while (focus != NULL) { - return gFocusMgr.childHasKeyboardFocus(child); - } - else - { - return FALSE; + if (focus->getName() == childname) + { + return TRUE; + } + + focus = focus->getParent(); } + + return FALSE; } //----------------------------------------------------------------------------- @@ -1707,14 +1537,14 @@ LLView* LLView::getChildView(const std::string& name, BOOL recurse, BOOL create_ BOOL LLView::parentPointInView(S32 x, S32 y, EHitTestType type) const { - return (mUseBoundingRect && type == HIT_TEST_USE_BOUNDING_RECT) + return (getUseBoundingRect() && type == HIT_TEST_USE_BOUNDING_RECT) ? mBoundingRect.pointInRect( x, y ) : mRect.pointInRect( x, y ); } BOOL LLView::pointInView(S32 x, S32 y, EHitTestType type) const { - return (mUseBoundingRect && type == HIT_TEST_USE_BOUNDING_RECT) + return (getUseBoundingRect() && type == HIT_TEST_USE_BOUNDING_RECT) ? mBoundingRect.pointInRect( x + mRect.mLeft, y + mRect.mBottom ) : mRect.localPointInRect( x, y ); } @@ -1789,6 +1619,7 @@ LLView* LLView::getRootView() return view; } + BOOL LLView::deleteViewByHandle(LLHandle handle) { LLView* viewp = handle.get(); @@ -1803,74 +1634,145 @@ BOOL LLView::deleteViewByHandle(LLHandle handle) return viewp != NULL; } +LLView* LLView::findPrevSibling(LLView* child) +{ + child_list_t::iterator prev_it = std::find(mChildList.begin(), mChildList.end(), child); + if (prev_it != mChildList.end() && prev_it != mChildList.begin()) + { + return *(--prev_it); + } + return NULL; +} + +LLView* LLView::findNextSibling(LLView* child) +{ + child_list_t::iterator next_it = std::find(mChildList.begin(), mChildList.end(), child); + if (next_it != mChildList.end()) + { + next_it++; + } + + return (next_it != mChildList.end()) ? *next_it : NULL; +} + + +LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BOOL allow_partial_outside) +{ + LLCoordGL delta; + + if (allow_partial_outside) + { + const S32 KEEP_ONSCREEN_PIXELS = 16; + + if( input.mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft ) + { + delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS); + } + else + if( input.mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight ) + { + delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS); + } + + if( input.mTop > constraint.mTop ) + { + delta.mY = constraint.mTop - input.mTop; + } + else + if( input.mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom ) + { + delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS); + } + } + else + { + if( input.mLeft < constraint.mLeft ) + { + delta.mX = constraint.mLeft - input.mLeft; + } + else + if( input.mRight > constraint.mRight ) + { + delta.mX = constraint.mRight - input.mRight; + // compensate for left edge possible going off screen + delta.mX += llmax( 0, input.getWidth() - constraint.getWidth() ); + } + + if( input.mTop > constraint.mTop ) + { + delta.mY = constraint.mTop - input.mTop; + } + else + if( input.mBottom < constraint.mBottom ) + { + delta.mY = constraint.mBottom - input.mBottom; + // compensate for top edge possible going off screen + delta.mY -= llmax( 0, input.getHeight() - constraint.getHeight() ); + } + } + + return delta; +} // Moves the view so that it is entirely inside of constraint. // If the view will not fit because it's too big, aligns with the top and left. // (Why top and left? That's where the drag bars are for floaters.) BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside ) { - S32 delta_x = 0; - S32 delta_y = 0; + LLCoordGL translation = getNeededTranslation(getRect(), constraint, allow_partial_outside); - if (allow_partial_outside) + if (translation.mX != 0 || translation.mY != 0) { - const S32 KEEP_ONSCREEN_PIXELS = 16; - - if( getRect().mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft ) - { - delta_x = constraint.mLeft - (getRect().mRight - KEEP_ONSCREEN_PIXELS); - } - else - if( getRect().mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight ) - { - delta_x = constraint.mRight - (getRect().mLeft + KEEP_ONSCREEN_PIXELS); - } - - if( getRect().mTop > constraint.mTop ) - { - delta_y = constraint.mTop - getRect().mTop; - } - else - if( getRect().mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom ) - { - delta_y = constraint.mBottom - (getRect().mTop - KEEP_ONSCREEN_PIXELS); - } - } - else - { - if( getRect().mLeft < constraint.mLeft ) - { - delta_x = constraint.mLeft - getRect().mLeft; - } - else - if( getRect().mRight > constraint.mRight ) - { - delta_x = constraint.mRight - getRect().mRight; - // compensate for left edge possible going off screen - delta_x += llmax( 0, getRect().getWidth() - constraint.getWidth() ); - } - - if( getRect().mTop > constraint.mTop ) - { - delta_y = constraint.mTop - getRect().mTop; - } - else - if( getRect().mBottom < constraint.mBottom ) - { - delta_y = constraint.mBottom - getRect().mBottom; - // compensate for top edge possible going off screen - delta_y -= llmax( 0, getRect().getHeight() - constraint.getHeight() ); - } - } - - if (delta_x != 0 || delta_y != 0) - { - translate(delta_x, delta_y); + translate(translation.mX, translation.mY); return TRUE; } return FALSE; } +// move this view into "inside" but not onto "exclude" +// NOTE: if this view is already contained in "inside", we ignore the "exclude" rect +BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside ) +{ + LLCoordGL translation = getNeededTranslation(getRect(), inside, allow_partial_outside); + + if (translation.mX != 0 || translation.mY != 0) + { + // translate ourselves into constraint rect + translate(translation.mX, translation.mY); + + // do we overlap with exclusion area? + // keep moving in the same direction to the other side of the exclusion rect + if (exclude.overlaps(getRect())) + { + // moving right + if (translation.mX > 0) + { + translate(exclude.mRight - getRect().mLeft, 0); + } + // moving left + else if (translation.mX < 0) + { + translate(exclude.mLeft - getRect().mRight, 0); + } + + // moving up + if (translation.mY > 0) + { + translate(0, exclude.mTop - getRect().mBottom); + } + // moving down + else if (translation.mY < 0) + { + translate(0, exclude.mBottom - getRect().mTop); + } + } + + return TRUE; + } + return FALSE; +} + + void LLView::centerWithin(const LLRect& bounds) { S32 left = bounds.mLeft + (bounds.getWidth() - getRect().getWidth()) / 2; @@ -2917,6 +2819,13 @@ LLSD LLView::getValue() const return LLSD(); } +S32 LLView::notifyParent(const LLSD& info) +{ + LLView* parent = getParent(); + if(parent) + return parent->notifyParent(info); + return 0; +} LLView* LLView::createWidget(LLXMLNodePtr xml_node) const { // forward requests to ui ctrl factory diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 51d75870c..721c82fbb 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -54,6 +54,7 @@ #include "stdenums.h" #include "lluistring.h" #include "llcursortypes.h" +#include "llinitparam.h" #include "llfocusmgr.h" const U32 FOLLOWS_NONE = 0x00; @@ -68,88 +69,6 @@ const BOOL NOT_MOUSE_OPAQUE = FALSE; const U32 GL_NAME_UI_RESERVED = 2; -/* -// virtual functions defined in LLView: - -virtual BOOL isCtrl() const; - LLUICtrl -virtual BOOL isPanel(); - LLPanel -virtual void setRect(const LLRect &rect); - LLLineEditor -virtual void addCtrl( LLUICtrl* ctrl, S32 tab_group); -virtual void addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group); -virtual void removeCtrl( LLUICtrl* ctrl); - LLPanel -virtual BOOL canFocusChildren() const { return TRUE; } - LLFolderView -virtual void deleteAllChildren(); - LLFolderView, LLPanelInventory -virtual void setTentative(BOOL b) {} - LLUICtrl, LLSliderCtrl, LLSpinCtrl -virtual BOOL getTentative() const { return FALSE; } - LLUICtrl, LLCheckBoxCtrl -virtual void setVisible(BOOL visible); - LLFloater, LLAlertDialog, LLMenuItemGL, LLModalDialog -virtual void setEnabled(BOOL enabled) { mEnabled = enabled; } - LLCheckBoxCtrl, LLComboBox, LLLineEditor, LLMenuGL, LLRadioGroup, etc -virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ) { return FALSE; } - LLUICtrl, LLButton, LLCheckBoxCtrl, LLLineEditor, LLMenuGL, LLSliderCtrl -virtual void handleVisibilityChange ( BOOL curVisibilityIn ); - LLMenuGL -virtual LLRect getSnapRect() const { return mRect; } *TODO: Make non virtual - LLFloater -virtual LLRect getRequiredRect() { return mRect; } - LLScrolllistCtrl -virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - LLUICtrl, et. al. -virtual void translate( S32 x, S32 y ); - LLMenuGL -virtual void handleReshape(const LLRect& new_rect, bool by_user = false); - LLFloater, LLScrollLIstVtrl -virtual LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0); -virtual LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0); - LLScrollListCtrl -virtual BOOL canSnapTo(const LLView* other_view) { return other_view != this && other_view->getVisible(); } - LLFloater -virtual void setSnappedTo(const LLView* snap_view) {} - LLFloater -virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); - * -virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); - * -virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,EDragAndDropType cargo_type,void* cargo_data,EAcceptance* accept,std::string& tooltip_msg); - * -virtual void draw(); - * - - * -virtual LLXMLNodePtr getXML(bool save_children = true) const; - * -virtual void initFromXML(LLXMLNodePtr node, LLView* parent); - * -virtual void onFocusLost() {} - LLUICtrl, LLScrollListCtrl, LLMenuGL, LLLineEditor, LLComboBox -virtual void onFocusReceived() {} - LLUICtrl, LLTextEditor, LLScrollListVtrl, LLMenuGL, LLLineEditor -virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; - LLTabContainer, LLPanel, LLMenuGL -virtual void setControlName(const std::string& control, LLView *context); - LLSliderCtrl, LLCheckBoxCtrl -virtual std::string getControlName() const { return mControlName; } - LLSliderCtrl, LLCheckBoxCtrl -virtual bool handleEvent(LLPointer event, const LLSD& userdata); - LLMenuItem -virtual void setValue(const LLSD& value); - * - -protected: -virtual BOOL handleKeyHere(KEY key, MASK mask); - * -virtual BOOL handleUnicodeCharHere(llwchar uni_char); - * -*/ - class LLUICtrlFactory; // maps xml strings to widget classes @@ -209,9 +128,73 @@ public: } }; -class LLView : public LLMouseHandler, public LLMortician, public LLFocusableElement +class LLView +: public LLMouseHandler, // handles mouse events + public LLFocusableElement, // handles keyboard events + public LLMortician // lazy deletion + //public LLHandleProvider // passes out weak references to self { +public: + struct Follows : public LLInitParam::ChoiceBlock + { + Alternative string; + Alternative flags; + Follows(); + }; + + struct Params : public LLInitParam::Block + { + Mandatory name; + + Optional enabled, + visible, + mouse_opaque, + use_bounding_rect, + from_xui, + focus_root; + + Optional tab_group, + default_tab_group; + Optional tool_tip; + + Optional sound_flags; + Optional follows; + Optional hover_cursor; + + Optional layout; + Optional rect; + + // Historical bottom-left layout used bottom_delta and left_delta + // for relative positioning. New layout "topleft" prefers specifying + // based on top edge. + Optional bottom_delta, // from last bottom to my bottom + top_pad, // from last bottom to my top + top_delta, // from last top to my top + left_pad, // from last right to my left + left_delta; // from last left to my left + + //FIXME: get parent context involved in parsing traversal + Ignored needs_translate, // cue for translation tools + xmlns, // xml namespace + xmlns_xsi, // xml namespace + xsi_schemaLocation, // xml schema + xsi_type; // xml schema type + + Params(); + }; + + void initFromParams(const LLView::Params&); + +protected: + LLView(const LLView::Params&); + //friend class LLUICtrlFactory; +private: + void init(const LLView::Params&); + +private: + // widgets in general are not copyable + LLView(const LLView& other) {}; public: #if LL_DEBUG static BOOL sIsDrawing; @@ -294,7 +277,9 @@ public: void setSoundFlags(U8 flags) { mSoundFlags = flags; } void setName(std::string name) { mName = name; } void setUseBoundingRect( BOOL use_bounding_rect ); - BOOL getUseBoundingRect(); + BOOL getUseBoundingRect() const; + + ECursorType getHoverCursor() { return mHoverCursor; } const std::string& getToolTip() const { return mToolTipMsg.getString(); } @@ -302,15 +287,14 @@ public: void sendChildToBack(LLView* child); void moveChildToFrontOfTabGroup(LLUICtrl* child); void moveChildToBackOfTabGroup(LLUICtrl* child); + + virtual bool addChild(LLView* view, S32 tab_group = 0); + + // implemented in terms of addChild() + bool addChildInBack(LLView* view, S32 tab_group = 0); - void addChild(LLView* view, S32 tab_group = 0); - void addChildAtEnd(LLView* view, S32 tab_group = 0); // remove the specified child from the view, and set it's parent to NULL. - void removeChild(LLView* view, BOOL deleteIt = FALSE); - - virtual void addCtrl( LLUICtrl* ctrl, S32 tab_group); - virtual void addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group); - virtual void removeCtrl( LLUICtrl* ctrl); + virtual void removeChild(LLView* view); child_tab_order_t getCtrlOrder() const { return mCtrlOrder; } ctrl_list_t getCtrlList() const; @@ -318,6 +302,7 @@ public: void setDefaultTabGroup(S32 d) { mDefaultTabGroup = d; } S32 getDefaultTabGroup() const { return mDefaultTabGroup; } + S32 getLastTabGroup() { return mLastTabGroup; } BOOL isInVisibleChain() const; BOOL isInEnabledChain() const; @@ -336,18 +321,19 @@ public: void setAllChildrenEnabled(BOOL b); virtual void setVisible(BOOL visible); - BOOL getVisible() const { return mVisible; } + const BOOL& getVisible() const { return mVisible; } virtual void setEnabled(BOOL enabled); BOOL getEnabled() const { return mEnabled; } U8 getSoundFlags() const { return mSoundFlags; } virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); - virtual void handleVisibilityChange ( BOOL curVisibilityIn ); + virtual void handleVisibilityChange ( BOOL new_visibility ); void pushVisible(BOOL visible) { mLastVisible = mVisible; setVisible(visible); } - void popVisible() { setVisible(mLastVisible); mLastVisible = TRUE; } - + void popVisible() { setVisible(mLastVisible); } + BOOL getLastVisible() const { return mLastVisible; } + LLHandle getHandle() { mHandle.bind(this); return mHandle; } U32 getFollows() const { return mReshapeFlags; } @@ -360,18 +346,22 @@ public: const LLRect& getRect() const { return mRect; } const LLRect& getBoundingRect() const { return mBoundingRect; } LLRect getLocalBoundingRect() const; - LLRect getScreenRect() const; + LLRect calcScreenRect() const; + LLRect calcScreenBoundingRect() const; LLRect getLocalRect() const; virtual LLRect getSnapRect() const; LLRect getLocalSnapRect() const; // Override and return required size for this object. 0 for width/height means don't care. virtual LLRect getRequiredRect(); + LLRect calcBoundingRect(); void updateBoundingRect(); LLView* getRootView(); LLView* getParent() const { return mParentView; } LLView* getFirstChild() const { return (mChildList.empty()) ? NULL : *(mChildList.begin()); } + LLView* findPrevSibling(LLView* child); + LLView* findNextSibling(LLView* child); S32 getChildCount() const { return (S32)mChildList.size(); } template void sortChildren(_Pr3 _Pred) { mChildList.sort(_Pred); } BOOL hasAncestor(const LLView* parentp) const; @@ -388,6 +378,7 @@ public: virtual void translate( S32 x, S32 y ); void setOrigin( S32 x, S32 y ) { mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); } BOOL translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside ); + BOOL translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside ); void centerWithin(const LLRect& bounds); void setShape(const LLRect& new_rect, bool by_user = false); @@ -422,10 +413,6 @@ public: BOOL getSaveToXML() const { return mSaveToXML; } void setSaveToXML(BOOL b) { mSaveToXML = b; } - // inherited from LLFocusableElement - /* virtual */ void onFocusLost(); - /* virtual */ void onFocusReceived(); - typedef enum e_hit_test_type { HIT_TEST_USE_BOUNDING_RECT, @@ -465,6 +452,8 @@ public: virtual LLSD getValue() const; const child_list_t* getChildList() const { return &mChildList; } + child_list_const_iter_t beginChild() const { return mChildList.begin(); } + child_list_const_iter_t endChild() const { return mChildList.end(); } // LLMouseHandler functions // Default behavior is to pass events to children @@ -592,12 +581,20 @@ public: static LLWindow* getWindow(void) { return LLUI::sWindow; } virtual void handleReshape(const LLRect& rect, bool by_user); -protected: + virtual BOOL handleKeyHere(KEY key, MASK mask); virtual BOOL handleUnicodeCharHere(llwchar uni_char); + + //send custom notification to LLView parent + virtual S32 notifyParent(const LLSD& info); +protected: void drawDebugRect(); void drawChild(LLView* childp, S32 x_offset = 0, S32 y_offset = 0, BOOL force_draw = FALSE); + void drawChildren(); + bool visibleAndContains(S32 local_x, S32 local_Y); + bool visibleEnabledAndContains(S32 local_x, S32 local_y); + void logMouseEvent(); LLView* childrenHandleKey(KEY key, MASK mask); LLView* childrenHandleUnicodeChar(llwchar uni_char); @@ -624,18 +621,36 @@ protected: control_map_t mFloaterControls; private: + + template + LLView* childrenHandleMouseEvent(const METHOD& method, S32 x, S32 y, XDATA extra, bool allow_mouse_block = true); + + template + LLView* childrenHandleCharEvent(const std::string& desc, const METHOD& method, + CHARTYPE c, MASK mask); + + // adapter to blur distinction between handleKey() and handleUnicodeChar() + // for childrenHandleCharEvent() + BOOL handleUnicodeCharWithDummyMask(llwchar uni_char, MASK /* dummy */, BOOL from_parent) + { + return handleUnicodeChar(uni_char, from_parent); + } + LLView* mParentView; child_list_t mChildList; - std::string mName; // location in pixels, relative to surrounding structure, bottom,left=0,0 + BOOL mVisible; LLRect mRect; LLRect mBoundingRect; + + std::string mName; U32 mReshapeFlags; child_tab_order_t mCtrlOrder; S32 mDefaultTabGroup; + S32 mLastTabGroup; BOOL mEnabled; // Enabled means "accepts input that has an effect on the state of the application." // A disabled view, for example, may still have a scrollbar that responds to mouse events. @@ -651,14 +666,9 @@ private: LLRootHandle mHandle; BOOL mLastVisible; - BOOL mVisible; - S32 mNextInsertionOrdinal; - // -public: - BOOL mDelayedDelete; - // + bool mInDraw; private: static LLWindow* sWindow; // All root views must know about their window. @@ -674,6 +684,34 @@ private: boost::signals2::connection mControlConnection; ECursorType mHoverCursor; + + // This allows special mouse-event targeting logic for testing. + typedef boost::function DrilldownFunc; + static DrilldownFunc sDrilldown; +public: + // This is the only public accessor to alter sDrilldown. This is not + // an accident. The intended usage pattern is like: + // { + // LLView::TemporaryDrilldownFunc scoped_func(myfunctor); + // // ... test with myfunctor ... + // } // exiting block restores original LLView::sDrilldown + class TemporaryDrilldownFunc: public boost::noncopyable + { + public: + TemporaryDrilldownFunc(const DrilldownFunc& func): + mOldDrilldown(sDrilldown) + { + sDrilldown = func; + } + + ~TemporaryDrilldownFunc() + { + sDrilldown = mOldDrilldown; + } + + private: + DrilldownFunc mOldDrilldown; + }; public: static BOOL sDebugRects; // Draw debug rects behind everything. diff --git a/indra/llui/llviewmodel.cpp b/indra/llui/llviewmodel.cpp new file mode 100644 index 000000000..a9f8acc44 --- /dev/null +++ b/indra/llui/llviewmodel.cpp @@ -0,0 +1,157 @@ +/** + * @file llviewmodel.cpp + * @author Nat Goodspeed + * @date 2008-08-08 + * @brief Implementation for llviewmodel. + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llviewmodel.h" +// STL headers +// std headers +// external library headers +// other Linden headers + +/// +LLViewModel::LLViewModel() + : mDirty(false) +{ +} + +/// Instantiate an LLViewModel with an existing data value +LLViewModel::LLViewModel(const LLSD& value) + : mDirty(false) +{ + setValue(value); +} + +/// Update the stored value +void LLViewModel::setValue(const LLSD& value) +{ + mValue = value; + mDirty = true; +} + +LLSD LLViewModel::getValue() const +{ + return mValue; +} + +//////////////////////////////////////////////////////////////////////////// + +/// +LLTextViewModel::LLTextViewModel() + : LLViewModel(false), + mUpdateFromDisplay(false) +{ +} + +/// Instantiate an LLViewModel with an existing data value +LLTextViewModel::LLTextViewModel(const LLSD& value) + : LLViewModel(value), + mUpdateFromDisplay(false) +{ +} + +/// Update the stored value +void LLTextViewModel::setValue(const LLSD& value) +{ + LLViewModel::setValue(value); + mDisplay = utf8str_to_wstring(value.asString()); + // mDisplay and mValue agree + mUpdateFromDisplay = false; +} + +void LLTextViewModel::setDisplay(const LLWString& value) +{ + // This is the strange way to alter the value. Normally we'd setValue() + // and do the utf8str_to_wstring() to get the corresponding mDisplay + // value. But a text editor might want to edit the display string + // directly, then convert back to UTF8 on commit. + mDisplay = value; + mDirty = true; + // Don't immediately convert to UTF8 -- do it lazily -- we expect many + // more setDisplay() calls than getValue() calls. Just flag that it needs + // doing. + mUpdateFromDisplay = true; +} + +LLSD LLTextViewModel::getValue() const +{ + // Has anyone called setDisplay() since the last setValue()? If so, have + // to convert mDisplay back to UTF8. + if (mUpdateFromDisplay) + { + // The fact that we're lazily updating fields in this object should be + // transparent to clients, which is why this method is left + // conventionally const. Nor do we particularly want to make these + // members mutable. Just cast away constness in this one place. + LLTextViewModel* nthis = const_cast(this); + nthis->mUpdateFromDisplay = false; + nthis->mValue = wstring_to_utf8str(mDisplay); + } + return LLViewModel::getValue(); +} + + +//////////////////////////////////////////////////////////////////////////// + +LLListViewModel::LLListViewModel(const LLSD& values) + : LLViewModel() +{ +} + +void LLListViewModel::addColumn(const LLSD& column, EAddPosition pos) +{ +} + +void LLListViewModel::clearColumns() +{ +} + +void LLListViewModel::setColumnLabel(const std::string& column, const std::string& label) +{ +} + +LLScrollListItem* LLListViewModel::addElement(const LLSD& value, EAddPosition pos, + void* userdata) +{ + return NULL; +} + +LLScrollListItem* LLListViewModel::addSimpleElement(const std::string& value, EAddPosition pos, + const LLSD& id) +{ + return NULL; +} + +void LLListViewModel::clearRows() +{ +} + +void LLListViewModel::sortByColumn(const std::string& name, bool ascending) +{ +} diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h new file mode 100644 index 000000000..763af5d8a --- /dev/null +++ b/indra/llui/llviewmodel.h @@ -0,0 +1,214 @@ +/** + * @file llviewmodel.h + * @author Nat Goodspeed + * @date 2008-08-08 + * @brief Define "View Model" classes intended to store data values for use + * by LLUICtrl subclasses. The phrase is borrowed from Microsoft + * terminology, in which "View Model" means the storage object + * underlying a specific widget object -- as in our case -- rather + * than the business "model" object underlying the overall "view" + * presented by the collection of widgets. + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLVIEWMODEL_H) +#define LL_LLVIEWMODEL_H + +#include "llpointer.h" +#include "llsd.h" +#include "llrefcount.h" +#include "stdenums.h" +#include "llstring.h" +#include + +class LLScrollListItem; + +class LLViewModel; +class LLTextViewModel; +class LLListViewModel; +// Because LLViewModel is derived from LLRefCount, always pass, store +// and return LLViewModelPtr rather than plain LLViewModel*. +typedef LLPointer LLViewModelPtr; +typedef LLPointer LLTextViewModelPtr; +typedef LLPointer LLListViewModelPtr; + +/** + * LLViewModel stores a scalar LLSD data item, the current display value of a + * scalar LLUICtrl widget. LLViewModel subclasses are used to store data + * collections used for aggregate widgets. LLViewModel is ref-counted because + * -- for multiple skins -- we may have distinct widgets sharing the same + * LLViewModel data. This way, the LLViewModel is quietly deleted when the + * last referencing widget is destroyed. + */ +class LLViewModel: public LLRefCount +{ +public: + LLViewModel(); + /// Instantiate an LLViewModel with an existing data value + LLViewModel(const LLSD& value); + + /// Update the stored value + virtual void setValue(const LLSD& value); + /// Get the stored value, in appropriate type. + virtual LLSD getValue() const; + + /// Has the value been changed since last time we checked? + bool isDirty() const { return mDirty; } + /// Once the value has been saved to a file, or otherwise consumed by the + /// app, we no longer need to enable the Save button + void resetDirty() { mDirty = false; } + // + void setDirty() { mDirty = true; } + +protected: + LLSD mValue; + bool mDirty; +}; + +/** + * LLTextViewModel stores a value displayed as text. + */ +class LLTextViewModel: public LLViewModel +{ +public: + LLTextViewModel(); + /// Instantiate an LLViewModel with an existing data value + LLTextViewModel(const LLSD& value); + + // LLViewModel functions + virtual void setValue(const LLSD& value); + virtual LLSD getValue() const; + + // New functions + /// Get the stored value in string form + const LLWString& getDisplay() const { return mDisplay; } + + /** + * Set the display string directly (see LLTextEditor). What the user is + * editing is actually the LLWString value rather than the underlying + * UTF-8 value. + */ + void setDisplay(const LLWString& value); + +private: + /// To avoid converting every widget's stored value from LLSD to LLWString + /// every frame, cache the converted value + LLWString mDisplay; + /// As the user edits individual characters (setDisplay()), defer + /// LLWString-to-UTF8 conversions until s/he's done. + bool mUpdateFromDisplay; +}; + +/** + * LLListViewModel stores a list of data items. The semantics are borrowed + * from LLScrollListCtrl. + */ +class LLListViewModel: public LLViewModel +{ +public: + LLListViewModel() {} + LLListViewModel(const LLSD& values); + + virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM); + virtual void clearColumns(); + virtual void setColumnLabel(const std::string& column, const std::string& label); + virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, + void* userdata = NULL); + virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos, + const LLSD& id); + virtual void clearRows(); + virtual void sortByColumn(const std::string& name, bool ascending); +}; + +//namespace LLViewModel +//{ +// class Value +// { +// public: +// Value(const LLSD& value = LLSD()); +// +// LLSD getValue() const { return mValue; } +// void setValue(const LLSD& value) { mValue = value; } +// +// bool isAvailable() const { return false; } +// bool isReadOnly() const { return false; } +// +// bool undo() { return false; } +// bool redo() { return false; } +// +// /// Has the value been changed since last time we checked? +// bool isDirty() const { return mDirty; } +// /// Once the value has been saved to a file, or otherwise consumed by the +// /// app, we no longer need to enable the Save button +// void resetDirty() { mDirty = false; } +// // +// void setDirty() { mDirty = true; } +// +// protected: +// LLSD mValue; +// bool mDirty; +// }; +// +// class Numeric : public Value +// { +// public: +// Numeric(S32 value = 0); +// Numeric(F32 value); +// +// F32 getPrecision(); +// F32 getMin(); +// F32 getMax(); +// +// void increment(); +// void decrement(); +// }; +// +// class MultipleValues : public Value +// { +// class Selector +// {}; +// +// MultipleValues(); +// virtual S32 numElements(); +// }; +// +// class Tuple : public MultipleValues +// { +// Tuple(S32 size); +// LLSD getValue(S32 which) const; +// void setValue(S32 which, const LLSD& value); +// }; +// +// class List : public MultipleValues +// { +// List(); +// +// void add(const ValueModel& value); +// bool remove(const Selector& item); +// +// void setSortElement(const Selector& element); +// void sort(); +// }; +// +//}; +#endif /* ! defined(LL_LLVIEWMODEL_H) */ diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp index a0f319a90..0d1c4b37f 100644 --- a/indra/llvfs/lldiriterator.cpp +++ b/indra/llvfs/lldiriterator.cpp @@ -133,7 +133,7 @@ bool LLDirIterator::Impl::next(std::string &fname) #else std::string name = mIter->path().filename(); #endif - if (found = boost::regex_match(name, match, mFilterExp)) + if ((found = boost::regex_match(name, match, mFilterExp))) { fname = name; } diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp index 21cfa66a8..85d41b5d3 100644 --- a/indra/llvfs/llpidlock.cpp +++ b/indra/llvfs/llpidlock.cpp @@ -54,6 +54,7 @@ static bool isProcessAlive(U32 pid) } #else //Everyone Else +#include static U32 getPID() { return getpid(); diff --git a/indra/llwindow/glh/glh_linear.h b/indra/llwindow/glh/glh_linear.h old mode 100644 new mode 100755 diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 21afee3fb..99d052521 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -174,6 +174,8 @@ public: // Provide native key event data virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); } + virtual void setTitle(const std::string &title){}; + protected: LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags); virtual ~LLWindow(); diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index c2705bbf7..9712ae1d9 100644 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -28,8 +28,6 @@ #include "llwindowcallbacks.h" -#include "llcoord.h" - // // LLWindowCallbacks // diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h index 6d353c479..804d4f7d8 100644 --- a/indra/llwindow/llwindowcallbacks.h +++ b/indra/llwindow/llwindowcallbacks.h @@ -26,7 +26,7 @@ #ifndef LLWINDOWCALLBACKS_H #define LLWINDOWCALLBACKS_H -class LLCoordGL; +#include "llcoord.h" class LLWindow; class LLWindowCallbacks diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index ecc5efd4e..06d7f237e 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -3269,6 +3269,15 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) } } +void LLWindowMacOSX::setTitle(const std::string &title) +{ + /*strncpy((char*)mWindowTitle + 1, title.c_str(), 253); + mWindowTitle[0] = title.length();*/ + + CFStringRef title_str = CFStringCreateWithCString(NULL, title.c_str(), kCFStringEncodingUTF8); + SetWindowTitleWithCFString(mWindow, title_str); +} + LLSD LLWindowMacOSX::getNativeKeyData() { LLSD result = LLSD::emptyMap(); diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index 504b446d1..3096a0aec 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -118,6 +118,8 @@ public: /*virtual*/ void interruptLanguageTextInput(); /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); + /*virtual*/ void setTitle(const std::string &title); + static std::vector getDynamicFallbackFontList(); // Provide native key event data diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index e7e6fe6b9..369b8ad88 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2502,8 +2502,8 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) std::string cmd, arg; cmd = gDirUtilp->getAppRODataDir(); cmd += gDirUtilp->getDirDelimiter(); - cmd += "etc"; - cmd += gDirUtilp->getDirDelimiter(); + //cmd += "etc"; + //cmd += gDirUtilp->getDirDelimiter(); cmd += "launch_url.sh"; arg = escaped_url; exec_cmd(cmd, arg); @@ -2512,6 +2512,11 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) llinfos << "spawn_web_browser returning." << llendl; } +void LLWindowSDL::setTitle(const std::string &title) +{ + mWindowTitle = title; + SDL_WM_SetCaption(mWindowTitle.c_str(),mWindowTitle.c_str()); +} void *LLWindowSDL::getPlatformWindow() { @@ -2616,8 +2621,9 @@ std::vector LLWindowSDL::getDynamicFallbackFontList() if (sortpat) { // Sort the list of system fonts from most-to-least-desirable. + FcResult fresult; fs = FcFontSort(NULL, sortpat, elide_unicode_coverage, - NULL, NULL); + NULL, &fresult); FcPatternDestroy(sortpat); } diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index a6b9ff4f9..4fbe89b5e 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -127,6 +127,8 @@ public: /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); + /*virtual*/ void setTitle(const std::string &title); + static std::vector getDynamicFallbackFontList(); // Not great that these are public, but they have to be accessible diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index b047c123d..9b4c297ce 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -3140,6 +3140,14 @@ void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async) ShellExecuteEx( &sei ); } +void LLWindowWin32::setTitle(const std::string &title) +{ + mbstowcs(mWindowTitle, title.c_str(), 255); + mWindowTitle[255] = 0; + + SetWindowText(mWindowHandle, mWindowTitle); +} + /* Make the raw keyboard data available - used to poke through to LLQtWebKit so that Qt/Webkit has access to the virtual keycodes etc. that it needs diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 9343593f6..fefe5d308 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -117,6 +117,8 @@ public: void ShellEx(const std::string& command); /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); + /*virtual*/ void setTitle(const std::string &title); + LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url ); static std::vector getDynamicFallbackFontList(); diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index db9caf8c0..b35585527 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -64,6 +64,7 @@ LLXMLNode::LLXMLNode() : mPrecision(64), mType(TYPE_CONTAINER), mEncoding(ENCODING_DEFAULT), + mLineNumber(-1), mParent(NULL), mChildren(NULL), mAttributes(), @@ -85,6 +86,7 @@ LLXMLNode::LLXMLNode(const char* name, BOOL is_attribute) : mPrecision(64), mType(TYPE_CONTAINER), mEncoding(ENCODING_DEFAULT), + mLineNumber(-1), mParent(NULL), mChildren(NULL), mAttributes(), @@ -106,6 +108,7 @@ LLXMLNode::LLXMLNode(LLStringTableEntry* name, BOOL is_attribute) : mPrecision(64), mType(TYPE_CONTAINER), mEncoding(ENCODING_DEFAULT), + mLineNumber(-1), mParent(NULL), mChildren(NULL), mAttributes(), @@ -127,6 +130,8 @@ LLXMLNode::LLXMLNode(const LLXMLNode& rhs) : mPrecision(rhs.mPrecision), mType(rhs.mType), mEncoding(rhs.mEncoding), + mLineNumber(0), + mParser(NULL), mParent(NULL), mChildren(NULL), mAttributes(), @@ -226,6 +231,10 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child) { mChildren->head = target_child->mNext; } + if (target_child == mChildren->tail) + { + mChildren->tail = target_child->mPrev; + } LLXMLNodePtr prev = target_child->mPrev; LLXMLNodePtr next = target_child->mNext; @@ -294,6 +303,22 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child) mChildren->tail = new_child; } } + // if after_child == parent, then put new_child at beginning + else if (after_child == this) + { + // add to front of list + new_child->mNext = mChildren->head; + if (mChildren->head) + { + mChildren->head->mPrev = new_child; + mChildren->head = new_child; + } + else // no children + { + mChildren->head = new_child; + mChildren->tail = new_child; + } + } else { if (after_child->mNext.notNull()) @@ -401,7 +426,8 @@ void XMLCALL StartXMLNode(void *userData, } new_node_ptr->mParser = parent->mParser; - + new_node_ptr->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser)); + // Set the current active node to the new node XML_Parser *parser = parent->mParser; XML_SetUserData(*parser, (void *)new_node_ptr); @@ -492,6 +518,7 @@ void XMLCALL StartXMLNode(void *userData, if (!new_node->getAttribute(attr_name.c_str(), attr_node, FALSE)) { attr_node = new LLXMLNode(attr_name.c_str(), TRUE); + attr_node->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser)); } attr_node->setValue(attr_value); new_node->addChild(attr_node); @@ -608,13 +635,14 @@ bool LLXMLNode::updateNode( } //update all of node's children with updateNodes children that match name - LLXMLNodePtr child; + LLXMLNodePtr child = node->getFirstChild(); + LLXMLNodePtr last_child = child; LLXMLNodePtr updateChild; for (updateChild = update_node->getFirstChild(); updateChild.notNull(); updateChild = updateChild->getNextSibling()) { - for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) + while(child.notNull()) { std::string nodeName; std::string updateName; @@ -633,6 +661,22 @@ bool LLXMLNode::updateNode( if ((nodeName != "") && (updateName == nodeName)) { updateNode(child, updateChild); + last_child = child; + child = child->getNextSibling(); + if (child.isNull()) + { + child = node->getFirstChild(); + } + break; + } + + child = child->getNextSibling(); + if (child.isNull()) + { + child = node->getFirstChild(); + } + if (child == last_child) + { break; } } @@ -670,14 +714,14 @@ bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXML LLFILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ if (fp == NULL) { - node = new LLXMLNode(); + node = NULL ; return false; } fseek(fp, 0, SEEK_END); U32 length = ftell(fp); fseek(fp, 0, SEEK_SET); - char *buffer = new char[length+1]; + U8* buffer = new U8[length+1]; size_t nread = fread(buffer, 1, length, fp); buffer[nread] = 0; fclose(fp); @@ -689,7 +733,7 @@ bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXML // static bool LLXMLNode::parseBuffer( - const char *buffer, + U8* buffer, U32 length, LLXMLNodePtr& node, LLXMLNode* defaults) @@ -708,7 +752,7 @@ bool LLXMLNode::parseBuffer( XML_SetUserData(my_parser, (void *)file_node_ptr); // Do the parsing - if (XML_Parse(my_parser, buffer, length, TRUE) != XML_STATUS_OK) + if (XML_Parse(my_parser, (const char *)buffer, length, TRUE) != XML_STATUS_OK) { llwarns << "Error parsing xml error code: " << XML_ErrorString(XML_GetErrorCode(my_parser)) @@ -723,7 +767,7 @@ bool LLXMLNode::parseBuffer( { llwarns << "Parse failure - wrong number of top-level nodes xml." << llendl; - node = new LLXMLNode(); + node = NULL ; return false; } @@ -761,7 +805,7 @@ bool LLXMLNode::parseStream( while(str.good()) { str.read((char*)buffer, BUFSIZE); - int count = str.gcount(); + int count = (int)str.gcount(); if (XML_Parse(my_parser, (const char *)buffer, count, !str.good()) != XML_STATUS_OK) { @@ -782,7 +826,7 @@ bool LLXMLNode::parseStream( { llwarns << "Parse failure - wrong number of top-level nodes xml." << llendl; - node = new LLXMLNode(); + node = NULL; return false; } @@ -836,12 +880,64 @@ BOOL LLXMLNode::isFullyDefault() } // static -void LLXMLNode::writeHeaderToFile(LLFILE *fOut) +bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root, + const std::vector& paths) { - fprintf(fOut, "\n"); + if (paths.empty()) return false; + + std::string filename = paths.front(); + if (filename.empty()) + { + return false; + } + + if (!LLXMLNode::parseFile(filename, root, NULL)) + { + llwarns << "Problem reading UI description file: " << filename << llendl; + return false; + } + + LLXMLNodePtr updateRoot; + + std::vector::const_iterator itor; + + for (itor = paths.begin(), ++itor; itor != paths.end(); ++itor) + { + std::string layer_filename = *itor; + if(layer_filename.empty() || layer_filename == filename) + { + // no localized version of this file, that's ok, keep looking + continue; + } + + if (!LLXMLNode::parseFile(layer_filename, updateRoot, NULL)) + { + llwarns << "Problem reading localized UI description file: " << layer_filename << llendl; + return false; + } + + std::string nodeName; + std::string updateName; + + updateRoot->getAttributeString("name", updateName); + root->getAttributeString("name", nodeName); + + if (updateName == nodeName) + { + LLXMLNode::updateNode(root, updateRoot); + } + } + + return true; } -void LLXMLNode::writeToFile(LLFILE *fOut, const std::string& indent) +// static +void LLXMLNode::writeHeaderToFile(LLFILE *out_file) +{ + fprintf(out_file, "\n"); +} + +void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent, bool use_type_decorations) { if (isFullyDefault()) { @@ -850,15 +946,16 @@ void LLXMLNode::writeToFile(LLFILE *fOut, const std::string& indent) } std::ostringstream ostream; - writeToOstream(ostream, indent); + writeToOstream(ostream, indent, use_type_decorations); std::string outstring = ostream.str(); - if (fwrite(outstring.c_str(), 1, outstring.length(), fOut) != outstring.length()) + size_t written = fwrite(outstring.c_str(), 1, outstring.length(), out_file); + if (written != outstring.length()) { llwarns << "Short write" << llendl; } } -void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& indent) +void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& indent, bool use_type_decorations) { if (isFullyDefault()) { @@ -872,84 +969,86 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i BOOL has_default_length = mDefault.isNull()?FALSE:(mLength == mDefault->mLength); // stream the name - output_stream << indent << "<" << mName->mString; + output_stream << indent << "<" << mName->mString << "\n"; - // ID - if (mID != "") + if (use_type_decorations) { - output_stream << " id=\"" << mID << "\""; - } - - // Type - if (!has_default_type) - { - switch (mType) + // ID + if (mID != "") { - case TYPE_BOOLEAN: - output_stream << " type=\"boolean\""; - break; - case TYPE_INTEGER: - output_stream << " type=\"integer\""; - break; - case TYPE_FLOAT: - output_stream << " type=\"float\""; - break; - case TYPE_STRING: - output_stream << " type=\"string\""; - break; - case TYPE_UUID: - output_stream << " type=\"uuid\""; - break; - case TYPE_NODEREF: - output_stream << " type=\"noderef\""; - break; - default: - // default on switch(enum) eliminates a warning on linux - break; - }; - } + output_stream << indent << " id=\"" << mID << "\"\n"; + } - // Encoding - if (!has_default_encoding) - { - switch (mEncoding) + // Type + if (!has_default_type) { - case ENCODING_DECIMAL: - output_stream << " encoding=\"decimal\""; - break; - case ENCODING_HEX: - output_stream << " encoding=\"hex\""; - break; - /*case ENCODING_BASE32: - output_stream << " encoding=\"base32\""; - break;*/ - default: - // default on switch(enum) eliminates a warning on linux - break; - }; - } + switch (mType) + { + case TYPE_BOOLEAN: + output_stream << indent << " type=\"boolean\"\n"; + break; + case TYPE_INTEGER: + output_stream << indent << " type=\"integer\"\n"; + break; + case TYPE_FLOAT: + output_stream << indent << " type=\"float\"\n"; + break; + case TYPE_STRING: + output_stream << indent << " type=\"string\"\n"; + break; + case TYPE_UUID: + output_stream << indent << " type=\"uuid\"\n"; + break; + case TYPE_NODEREF: + output_stream << indent << " type=\"noderef\"\n"; + break; + default: + // default on switch(enum) eliminates a warning on linux + break; + }; + } - // Precision - if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT)) - { - output_stream << " precision=\"" << mPrecision << "\""; - } + // Encoding + if (!has_default_encoding) + { + switch (mEncoding) + { + case ENCODING_DECIMAL: + output_stream << indent << " encoding=\"decimal\"\n"; + break; + case ENCODING_HEX: + output_stream << indent << " encoding=\"hex\"\n"; + break; + /*case ENCODING_BASE32: + output_stream << indent << " encoding=\"base32\"\n"; + break;*/ + default: + // default on switch(enum) eliminates a warning on linux + break; + }; + } - // Version - if (mVersionMajor > 0 || mVersionMinor > 0) - { - output_stream << " version=\"" << mVersionMajor << "." << mVersionMinor << "\""; - } + // Precision + if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT)) + { + output_stream << indent << " precision=\"" << mPrecision << "\"\n"; + } - // Array length - if (!has_default_length && mLength > 0) - { - output_stream << " length=\"" << mLength << "\""; + // Version + if (mVersionMajor > 0 || mVersionMinor > 0) + { + output_stream << indent << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"\n"; + } + + // Array length + if (!has_default_length && mLength > 0) + { + output_stream << indent << " length=\"" << mLength << "\"\n"; + } } { // Write out attributes - S32 col_pos = 0; LLXMLAttribList::const_iterator attr_itr; LLXMLAttribList::const_iterator attr_end = mAttributes.end(); for (attr_itr = mAttributes.begin(); attr_itr != attr_end; ++attr_itr) @@ -958,12 +1057,13 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i if (child->mDefault.isNull() || child->mDefault->mValue != child->mValue) { std::string attr = child->mName->mString; - if (attr == "id" || - attr == "type" || - attr == "encoding" || - attr == "precision" || - attr == "version" || - attr == "length") + if (use_type_decorations + && (attr == "id" || + attr == "type" || + attr == "encoding" || + attr == "precision" || + attr == "version" || + attr == "length")) { continue; // skip built-in attributes } @@ -971,17 +1071,14 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i std::string attr_str = llformat(" %s=\"%s\"", attr.c_str(), escapeXML(child->mValue).c_str()); - if (col_pos + (S32)attr_str.length() > MAX_COLUMN_WIDTH) - { - output_stream << "\n" << indent << " "; - col_pos = 4; - } - col_pos += attr_str.length(); - output_stream << attr_str; + output_stream << indent << attr_str << "\n"; } } } + // erase last \n before attaching final > or /> + output_stream.seekp(-1, std::ios::cur); + if (mChildren.isNull() && mValue == "") { output_stream << " />\n"; @@ -993,16 +1090,16 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i if (mChildren.notNull()) { // stream non-attributes - std::string next_indent = indent + "\t"; + std::string next_indent = indent + " "; for (LLXMLNode* child = getFirstChild(); child; child = child->getNextSibling()) { - child->writeToOstream(output_stream, next_indent); + child->writeToOstream(output_stream, next_indent, use_type_decorations); } } if (!mValue.empty()) { std::string contents = getTextContents(); - output_stream << indent << "\t" << escapeXML(contents) << "\n"; + output_stream << indent << " " << escapeXML(contents) << "\n"; } output_stream << indent << "mString << ">\n"; } @@ -1130,7 +1227,7 @@ bool LLXMLNode::getChild(const LLStringTableEntry* name, LLXMLNodePtr& node, BOO { return mDefault->getChild(name, node, FALSE); } - node = new LLXMLNode(); + node = NULL; return false; } @@ -1201,7 +1298,7 @@ bool LLXMLNode::getAttribute(const LLStringTableEntry* name, LLXMLNodePtr& node, { return mDefault->getAttribute(name, node, FALSE); } - node = new LLXMLNode(); + return false; } @@ -2475,14 +2572,15 @@ std::string LLXMLNode::escapeXML(const std::string& xml) return out; } -void LLXMLNode::setStringValue(U32 length, const std::string *array) +void LLXMLNode::setStringValue(U32 length, const std::string *strings) { if (length == 0) return; std::string new_value; for (U32 pos=0; pos @@ -44,10 +44,11 @@ #include #include "indra_constants.h" -#include "llmemory.h" -#include "llthread.h" +#include "llpointer.h" +#include "llthread.h" // LLThreadSafeRefCount #include "llstring.h" #include "llstringtable.h" +#include "llfile.h" class LLVector3; @@ -141,7 +142,7 @@ public: LLXMLNodePtr& node, LLXMLNode* defaults_tree); static bool parseBuffer( - const char *buffer, + U8* buffer, U32 length, LLXMLNodePtr& node, LLXMLNode* defaults); @@ -153,9 +154,18 @@ public: LLXMLNodePtr& node, LLXMLNodePtr& update_node); static LLXMLNodePtr replaceNode(LLXMLNodePtr node, LLXMLNodePtr replacement_node); - static void writeHeaderToFile(LLFILE *fOut); - void writeToFile(LLFILE *fOut, const std::string& indent = std::string()); - void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string()); + + static bool getLayeredXMLNode(LLXMLNodePtr& root, const std::vector& paths); + + + // Write standard XML file header: + // + static void writeHeaderToFile(LLFILE *out_file); + + // Write XML to file with one attribute per line. + // XML escapes values as they are written. + void writeToFile(LLFILE *out_file, const std::string& indent = std::string(), bool use_type_decorations=true); + void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string(), bool use_type_decorations=true); // Utility void findName(const std::string& name, LLXMLNodeList &results); @@ -207,6 +217,7 @@ public: U32 getLength() const { return mLength; } U32 getPrecision() const { return mPrecision; } const std::string& getValue() const { return mValue; } + std::string getSanitizedValue() const; std::string getTextContents() const; const LLStringTableEntry* getName() const { return mName; } BOOL hasName(const char* name) const { return mName == gStringTable.checkStringEntry(name); } @@ -227,6 +238,8 @@ public: bool getAttribute(const char* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE); bool getAttribute(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE); + S32 getLineNumber(); + // The following skip over attributes LLXMLNodePtr getFirstChild() const; LLXMLNodePtr getNextSibling() const; @@ -262,6 +275,8 @@ public: void setName(const std::string& name); void setName(LLStringTableEntry* name); + void setLineNumber(S32 line_number); + // Escapes " (quot) ' (apos) & (amp) < (lt) > (gt) static std::string escapeXML(const std::string& xml); @@ -300,6 +315,7 @@ public: U32 mPrecision; // The number of BITS per array item ValueType mType; // The value type Encoding mEncoding; // The value encoding + S32 mLineNumber; // line number in source file, if applicable LLXMLNode* mParent; // The parent node LLXMLChildrenPtr mChildren; // The child nodes diff --git a/indra/llxuixml/CMakeLists.txt b/indra/llxuixml/CMakeLists.txt new file mode 100644 index 000000000..bc98a43bd --- /dev/null +++ b/indra/llxuixml/CMakeLists.txt @@ -0,0 +1,40 @@ +# -*- cmake -*- + +project(llxuixml) + +include(00-Common) +include(LLCommon) +include(LLMath) +include(LLXML) + +include_directories( + ${LLCOMMON_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLXML_INCLUDE_DIRS} + ) + +set(llxuixml_SOURCE_FILES + llinitparam.cpp + lluicolor.cpp + ) + +set(llxuixml_HEADER_FILES + CMakeLists.txt + + llinitparam.h + lluicolor.h + ) + +set_source_files_properties(${llxuixml_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND llxuixml_SOURCE_FILES ${llxuixml_HEADER_FILES}) + +add_library (llxuixml ${llxuixml_SOURCE_FILES}) +# Libraries on which this library depends, needed for Linux builds +# Sort by high-level to low-level +target_link_libraries(llxuixml + llxml + llcommon + llmath + ) diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp new file mode 100644 index 000000000..db72aa19b --- /dev/null +++ b/indra/llxuixml/llinitparam.cpp @@ -0,0 +1,469 @@ +/** + * @file llinitparam.cpp + * @brief parameter block abstraction for creating complex objects and + * parsing construction parameters from xml and LLSD + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llinitparam.h" + + +namespace LLInitParam +{ + // + // Param + // + Param::Param(BaseBlock* enclosing_block) + : mIsProvided(false) + { + const U8* my_addr = reinterpret_cast(this); + const U8* block_addr = reinterpret_cast(enclosing_block); + mEnclosingBlockOffset = 0x7FFFffff & (U32)(my_addr - block_addr); + } + + // + // ParamDescriptor + // + ParamDescriptor::ParamDescriptor(param_handle_t p, + merge_func_t merge_func, + deserialize_func_t deserialize_func, + serialize_func_t serialize_func, + validation_func_t validation_func, + inspect_func_t inspect_func, + S32 min_count, + S32 max_count) + : mParamHandle(p), + mMergeFunc(merge_func), + mDeserializeFunc(deserialize_func), + mSerializeFunc(serialize_func), + mValidationFunc(validation_func), + mInspectFunc(inspect_func), + mMinCount(min_count), + mMaxCount(max_count), + mUserData(NULL) + {} + + ParamDescriptor::ParamDescriptor() + : mParamHandle(0), + mMergeFunc(NULL), + mDeserializeFunc(NULL), + mSerializeFunc(NULL), + mValidationFunc(NULL), + mInspectFunc(NULL), + mMinCount(0), + mMaxCount(0), + mUserData(NULL) + {} + + ParamDescriptor::~ParamDescriptor() + { + delete mUserData; + } + + // + // Parser + // + Parser::~Parser() + {} + + void Parser::parserWarning(const std::string& message) + { + if (mParseSilently) return; + llwarns << message << llendl; + } + + void Parser::parserError(const std::string& message) + { + if (mParseSilently) return; + llerrs << message << llendl; + } + + + // + // BlockDescriptor + // + void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data) + { + mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end()); + std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams)); + std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList)); + std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams)); + } + + BlockDescriptor::BlockDescriptor() + : mMaxParamOffset(0), + mInitializationState(UNINITIALIZED), + mCurrentBlockPtr(NULL) + {} + + // called by each derived class in least to most derived order + void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size) + { + descriptor.mCurrentBlockPtr = this; + descriptor.mMaxParamOffset = block_size; + + switch(descriptor.mInitializationState) + { + case BlockDescriptor::UNINITIALIZED: + // copy params from base class here + descriptor.aggregateBlockData(base_descriptor); + + descriptor.mInitializationState = BlockDescriptor::INITIALIZING; + break; + case BlockDescriptor::INITIALIZING: + descriptor.mInitializationState = BlockDescriptor::INITIALIZED; + break; + case BlockDescriptor::INITIALIZED: + // nothing to do + break; + } + } + + param_handle_t BaseBlock::getHandleFromParam(const Param* param) const + { + const U8* param_address = reinterpret_cast(param); + const U8* baseblock_address = reinterpret_cast(this); + return (param_address - baseblock_address); + } + + bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent) + { + if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), true)) + { + if (!silent) + { + p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str())); + } + return false; + } + return true; + } + + + bool BaseBlock::validateBlock(bool emit_errors) const + { + const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); + for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it) + { + const Param* param = getParamFromHandle(it->first); + if (!it->second(param)) + { + if (emit_errors) + { + llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl; + } + return false; + } + } + return true; + } + + void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const + { + // named param is one like LLView::Params::follows + // unnamed param is like LLView::Params::rect - implicit + const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); + + for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); + it != block_data.mUnnamedParams.end(); + ++it) + { + param_handle_t param_handle = (*it)->mParamHandle; + const Param* param = getParamFromHandle(param_handle); + ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc; + if (serialize_func) + { + const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; + // each param descriptor remembers its serial number + // so we can inspect the same param under different names + // and see that it has the same number + name_stack.push_back(std::make_pair("", true)); + serialize_func(*param, parser, name_stack, diff_param); + name_stack.pop_back(); + } + } + + for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); + it != block_data.mNamedParams.end(); + ++it) + { + param_handle_t param_handle = it->second->mParamHandle; + const Param* param = getParamFromHandle(param_handle); + ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc; + if (serialize_func && param->anyProvided()) + { + // Ensure this param has not already been serialized + // Prevents from being serialized as its own tag. + bool duplicate = false; + for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); + it2 != block_data.mUnnamedParams.end(); + ++it2) + { + if (param_handle == (*it2)->mParamHandle) + { + duplicate = true; + break; + } + } + + //FIXME: for now, don't attempt to serialize values under synonyms, as current parsers + // don't know how to detect them + if (duplicate) + { + continue; + } + + name_stack.push_back(std::make_pair(it->first, !duplicate)); + const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; + serialize_func(*param, parser, name_stack, diff_param); + name_stack.pop_back(); + } + } + } + + bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const + { + // named param is one like LLView::Params::follows + // unnamed param is like LLView::Params::rect - implicit + const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); + + for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); + it != block_data.mUnnamedParams.end(); + ++it) + { + param_handle_t param_handle = (*it)->mParamHandle; + const Param* param = getParamFromHandle(param_handle); + ParamDescriptor::inspect_func_t inspect_func = (*it)->mInspectFunc; + if (inspect_func) + { + name_stack.push_back(std::make_pair("", true)); + inspect_func(*param, parser, name_stack, (*it)->mMinCount, (*it)->mMaxCount); + name_stack.pop_back(); + } + } + + for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); + it != block_data.mNamedParams.end(); + ++it) + { + param_handle_t param_handle = it->second->mParamHandle; + const Param* param = getParamFromHandle(param_handle); + ParamDescriptor::inspect_func_t inspect_func = it->second->mInspectFunc; + if (inspect_func) + { + // Ensure this param has not already been inspected + bool duplicate = false; + for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); + it2 != block_data.mUnnamedParams.end(); + ++it2) + { + if (param_handle == (*it2)->mParamHandle) + { + duplicate = true; + break; + } + } + + name_stack.push_back(std::make_pair(it->first, !duplicate)); + inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount); + name_stack.pop_back(); + } + } + + return true; + } + + bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool ignored) + { + BlockDescriptor& block_data = mostDerivedBlockDescriptor(); + bool names_left = name_stack_range.first != name_stack_range.second; + + bool new_name = names_left + ? name_stack_range.first->second + : true; + + if (names_left) + { + const std::string& top_name = name_stack_range.first->first; + + ParamDescriptor::deserialize_func_t deserialize_func = NULL; + Param* paramp = NULL; + + BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name); + if (found_it != block_data.mNamedParams.end()) + { + // find pointer to member parameter from offset table + paramp = getParamFromHandle(found_it->second->mParamHandle); + deserialize_func = found_it->second->mDeserializeFunc; + + Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second); + ++new_name_stack.first; + if (deserialize_func(*paramp, p, new_name_stack, new_name)) + { + // value is no longer new, we know about it now + name_stack_range.first->second = false; + return true; + } + else + { + return false; + } + } + } + + // try to parse unnamed parameters, in declaration order + for ( BlockDescriptor::param_list_t::iterator it = block_data.mUnnamedParams.begin(); + it != block_data.mUnnamedParams.end(); + ++it) + { + Param* paramp = getParamFromHandle((*it)->mParamHandle); + ParamDescriptor::deserialize_func_t deserialize_func = (*it)->mDeserializeFunc; + + if (deserialize_func && deserialize_func(*paramp, p, name_stack_range, new_name)) + { + return true; + } + } + + // if no match, and no names left on stack, this is just an existence assertion of this block + // verify by calling readValue with NoParamValue type, an inherently unparseable type + if (!names_left) + { + Flag no_value; + return p.readValue(no_value); + } + + return false; + } + + //static + void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name) + { + // create a copy of the param descriptor in mAllParams + // so other data structures can store a pointer to it + block_data.mAllParams.push_back(in_param); + ParamDescriptorPtr param(block_data.mAllParams.back()); + + std::string name(char_name); + if ((size_t)param->mParamHandle > block_data.mMaxParamOffset) + { + llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block" << llendl; + } + + if (name.empty()) + { + block_data.mUnnamedParams.push_back(param); + } + else + { + // don't use insert, since we want to overwrite existing entries + block_data.mNamedParams[name] = param; + } + + if (param->mValidationFunc) + { + block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); + } + } + + void BaseBlock::addSynonym(Param& param, const std::string& synonym) + { + BlockDescriptor& block_data = mostDerivedBlockDescriptor(); + if (block_data.mInitializationState == BlockDescriptor::INITIALIZING) + { + param_handle_t handle = getHandleFromParam(¶m); + + // check for invalid derivation from a paramblock (i.e. without using + // Block + if ((size_t)handle > block_data.mMaxParamOffset) + { + llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block" << llendl; + } + + ParamDescriptorPtr param_descriptor = findParamDescriptor(param); + if (param_descriptor) + { + if (synonym.empty()) + { + block_data.mUnnamedParams.push_back(param_descriptor); + } + else + { + block_data.mNamedParams[synonym] = param_descriptor; + } + } + } + } + + const std::string& BaseBlock::getParamName(const BlockDescriptor& block_data, const Param* paramp) const + { + param_handle_t handle = getHandleFromParam(paramp); + for (BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it) + { + if (it->second->mParamHandle == handle) + { + return it->first; + } + } + + return LLStringUtil::null; + } + + ParamDescriptorPtr BaseBlock::findParamDescriptor(const Param& param) + { + param_handle_t handle = getHandleFromParam(¶m); + BlockDescriptor& descriptor = mostDerivedBlockDescriptor(); + BlockDescriptor::all_params_list_t::iterator end_it = descriptor.mAllParams.end(); + for (BlockDescriptor::all_params_list_t::iterator it = descriptor.mAllParams.begin(); + it != end_it; + ++it) + { + if ((*it)->mParamHandle == handle) return *it; + } + return ParamDescriptorPtr(); + } + + // take all provided params from other and apply to self + // NOTE: this requires that "other" is of the same derived type as this + bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) + { + bool some_param_changed = false; + BlockDescriptor::all_params_list_t::const_iterator end_it = block_data.mAllParams.end(); + for (BlockDescriptor::all_params_list_t::const_iterator it = block_data.mAllParams.begin(); + it != end_it; + ++it) + { + const Param* other_paramp = other.getParamFromHandle((*it)->mParamHandle); + ParamDescriptor::merge_func_t merge_func = (*it)->mMergeFunc; + if (merge_func) + { + Param* paramp = getParamFromHandle((*it)->mParamHandle); + llassert(paramp->mEnclosingBlockOffset == (*it)->mParamHandle); + some_param_changed |= merge_func(*paramp, *other_paramp, overwrite); + } + } + return some_param_changed; + } +} diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h new file mode 100644 index 000000000..7285d3c48 --- /dev/null +++ b/indra/llxuixml/llinitparam.h @@ -0,0 +1,2294 @@ +/** + * @file llinitparam.h + * @brief parameter block abstraction for creating complex objects and + * parsing construction parameters from xml and LLSD + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPARAM_H +#define LL_LLPARAM_H + +#include +#include +#include +#include +#include + +#include "llerror.h" + +namespace LLInitParam +{ + // used to indicate no matching value to a given name when parsing + struct Flag{}; + + template const T& defaultValue() { static T value; return value; } + + template ::value > + struct ParamCompare + { + static bool equals(const T &a, const T &b) + { + return a == b; + } + }; + + // boost function types are not comparable + template + struct ParamCompare + { + static bool equals(const T&a, const T &b) + { + return false; + } + }; + + template<> + struct ParamCompare + { + static bool equals(const LLSD &a, const LLSD &b) { return false; } + }; + + template<> + struct ParamCompare + { + static bool equals(const Flag& a, const Flag& b) { return false; } + }; + + + // helper functions and classes + typedef ptrdiff_t param_handle_t; + + // empty default implementation of key cache + // leverages empty base class optimization + template + class TypeValues + { + private: + struct Inaccessable{}; + public: + typedef std::map value_name_map_t; + typedef Inaccessable name_t; + + void setValueName(const std::string& key) {} + std::string getValueName() const { return ""; } + std::string calcValueName(const T& value) const { return ""; } + void clearValueName() const {} + + static bool getValueFromName(const std::string& name, T& value) + { + return false; + } + + static bool valueNamesExist() + { + return false; + } + + static std::vector* getPossibleValues() + { + return NULL; + } + + static value_name_map_t* getValueNames() {return NULL;} + }; + + template > + class TypeValuesHelper + { + public: + typedef typename std::map value_name_map_t; + typedef std::string name_t; + + //TODO: cache key by index to save on param block size + void setValueName(const std::string& value_name) + { + mValueName = value_name; + } + + std::string getValueName() const + { + return mValueName; + } + + std::string calcValueName(const T& value) const + { + value_name_map_t* map = getValueNames(); + for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end(); + it != end_it; + ++it) + { + if (ParamCompare::equals(it->second, value)) + { + return it->first; + } + } + + return ""; + } + + void clearValueName() const + { + mValueName.clear(); + } + + static bool getValueFromName(const std::string& name, T& value) + { + value_name_map_t* map = getValueNames(); + typename value_name_map_t::iterator found_it = map->find(name); + if (found_it == map->end()) return false; + + value = found_it->second; + return true; + } + + static bool valueNamesExist() + { + return !getValueNames()->empty(); + } + + static value_name_map_t* getValueNames() + { + static value_name_map_t sMap; + static bool sInitialized = false; + + if (!sInitialized) + { + sInitialized = true; + DERIVED_TYPE::declareValues(); + } + return &sMap; + } + + static std::vector* getPossibleValues() + { + static std::vector sValues; + + value_name_map_t* map = getValueNames(); + for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end(); + it != end_it; + ++it) + { + sValues.push_back(it->first); + } + return &sValues; + } + + static void declare(const std::string& name, const T& value) + { + (*getValueNames())[name] = value; + } + + protected: + static void getName(const std::string& name, const T& value) + {} + + mutable std::string mValueName; + }; + + class Parser + { + LOG_CLASS(Parser); + + public: + + struct CompareTypeID + { + bool operator()(const std::type_info* lhs, const std::type_info* rhs) const + { + return lhs->before(*rhs); + } + }; + + typedef std::vector > name_stack_t; + typedef std::pair name_stack_range_t; + typedef std::vector possible_values_t; + + typedef bool (*parser_read_func_t)(Parser& parser, void* output); + typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&); + typedef boost::function parser_inspect_func_t; + + typedef std::map parser_read_func_map_t; + typedef std::map parser_write_func_map_t; + typedef std::map parser_inspect_func_map_t; + + Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map) + : mParseSilently(false), + mParserReadFuncs(&read_map), + mParserWriteFuncs(&write_map), + mParserInspectFuncs(&inspect_map) + {} + virtual ~Parser(); + + template bool readValue(T& param) + { + parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); + if (found_it != mParserReadFuncs->end()) + { + return found_it->second(*this, (void*)¶m); + } + return false; + } + + template bool writeValue(const T& param, name_stack_t& name_stack) + { + parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T)); + if (found_it != mParserWriteFuncs->end()) + { + return found_it->second(*this, (const void*)¶m, name_stack); + } + return false; + } + + // dispatch inspection to registered inspection functions, for each parameter in a param block + template bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values) + { + parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T)); + if (found_it != mParserInspectFuncs->end()) + { + found_it->second(name_stack, min_count, max_count, possible_values); + return true; + } + return false; + } + + virtual std::string getCurrentElementName() = 0; + virtual void parserWarning(const std::string& message); + virtual void parserError(const std::string& message); + void setParseSilently(bool silent) { mParseSilently = silent; } + + protected: + template + void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL) + { + mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func)); + mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func)); + } + + template + void registerInspectFunc(parser_inspect_func_t inspect_func) + { + mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func)); + } + + bool mParseSilently; + + private: + parser_read_func_map_t* mParserReadFuncs; + parser_write_func_map_t* mParserWriteFuncs; + parser_inspect_func_map_t* mParserInspectFuncs; + }; + + class Param; + + // various callbacks and constraints associated with an individual param + struct ParamDescriptor + { + struct UserData + { + virtual ~UserData() {} + }; + + typedef bool(*merge_func_t)(Param&, const Param&, bool); + typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool); + typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param); + typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count); + typedef bool(*validation_func_t)(const Param*); + + ParamDescriptor(param_handle_t p, + merge_func_t merge_func, + deserialize_func_t deserialize_func, + serialize_func_t serialize_func, + validation_func_t validation_func, + inspect_func_t inspect_func, + S32 min_count, + S32 max_count); + + ParamDescriptor(); + ~ParamDescriptor(); + + param_handle_t mParamHandle; + merge_func_t mMergeFunc; + deserialize_func_t mDeserializeFunc; + serialize_func_t mSerializeFunc; + inspect_func_t mInspectFunc; + validation_func_t mValidationFunc; + S32 mMinCount; + S32 mMaxCount; + S32 mNumRefs; + UserData* mUserData; + }; + + typedef boost::shared_ptr ParamDescriptorPtr; + + // each derived Block class keeps a static data structure maintaining offsets to various params + class BlockDescriptor + { + public: + BlockDescriptor(); + + typedef enum e_initialization_state + { + UNINITIALIZED, + INITIALIZING, + INITIALIZED + } EInitializationState; + + void aggregateBlockData(BlockDescriptor& src_block_data); + + typedef boost::unordered_map param_map_t; + typedef std::vector param_list_t; + typedef std::list all_params_list_t; + typedef std::vector > param_validation_list_t; + + param_map_t mNamedParams; // parameters with associated names + param_list_t mUnnamedParams; // parameters with_out_ associated names + param_validation_list_t mValidationList; // parameters that must be validated + all_params_list_t mAllParams; // all parameters, owns descriptors + size_t mMaxParamOffset; + EInitializationState mInitializationState; // whether or not static block data has been initialized + class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed + }; + + class BaseBlock + { + public: + //TODO: implement in terms of owned_ptr + template + class Lazy + { + public: + Lazy() + : mPtr(NULL) + {} + + ~Lazy() + { + delete mPtr; + } + + Lazy(const Lazy& other) + { + if (other.mPtr) + { + mPtr = new T(*other.mPtr); + } + else + { + mPtr = NULL; + } + } + + Lazy& operator = (const Lazy& other) + { + if (other.mPtr) + { + mPtr = new T(*other.mPtr); + } + else + { + mPtr = NULL; + } + return *this; + } + + bool empty() const + { + return mPtr == NULL; + } + + void set(const T& other) + { + delete mPtr; + mPtr = new T(other); + } + + const T& get() const + { + return ensureInstance(); + } + + T& get() + { + return ensureInstance(); + } + + private: + // lazily allocate an instance of T + T* ensureInstance() const + { + if (mPtr == NULL) + { + mPtr = new T(); + } + return mPtr; + } + + private: + // if you get a compilation error with this, that means you are using a forward declared struct for T + // unfortunately, the type traits we rely on don't work with forward declared typed + //static const int dummy = sizeof(T); + + mutable T* mPtr; + }; + + // "Multiple" constraint types, put here in root class to avoid ambiguity during use + struct AnyAmount + { + enum { minCount = 0 }; + enum { maxCount = U32_MAX }; + }; + + template + struct AtLeast + { + enum { minCount = MIN_AMOUNT }; + enum { maxCount = U32_MAX }; + }; + + template + struct AtMost + { + enum { minCount = 0 }; + enum { maxCount = MAX_AMOUNT }; + }; + + template + struct Between + { + enum { minCount = MIN_AMOUNT }; + enum { maxCount = MAX_AMOUNT }; + }; + + template + struct Exactly + { + enum { minCount = EXACT_COUNT }; + enum { maxCount = EXACT_COUNT }; + }; + + // this typedef identifies derived classes as being blocks + typedef void baseblock_base_class_t; + LOG_CLASS(BaseBlock); + friend class Param; + + virtual ~BaseBlock() {} + bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false); + + param_handle_t getHandleFromParam(const Param* param) const; + bool validateBlock(bool emit_errors = true) const; + + Param* getParamFromHandle(const param_handle_t param_handle) + { + if (param_handle == 0) return NULL; + + U8* baseblock_address = reinterpret_cast(this); + return reinterpret_cast(baseblock_address + param_handle); + } + + const Param* getParamFromHandle(const param_handle_t param_handle) const + { + const U8* baseblock_address = reinterpret_cast(this); + return reinterpret_cast(baseblock_address + param_handle); + } + + void addSynonym(Param& param, const std::string& synonym); + + // Blocks can override this to do custom tracking of changes + virtual void paramChanged(const Param& changed_param, bool user_provided) {} + + bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; + bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const; + + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + + // take all provided params from other and apply to self + bool overwriteFrom(const BaseBlock& other) + { + return false; + } + + // take all provided params that are not already provided, and apply to self + bool fillFrom(const BaseBlock& other) + { + return false; + } + + static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name); + + ParamDescriptorPtr findParamDescriptor(const Param& param); + + protected: + void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size); + + + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite) + { + return mergeBlock(block_data, source, overwrite); + } + // take all provided params from other and apply to self + bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); + + static BlockDescriptor& selfBlockDescriptor() + { + static BlockDescriptor sBlockDescriptor; + return sBlockDescriptor; + } + + private: + const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; + }; + + template + struct ParamCompare, false > + { + static bool equals(const BaseBlock::Lazy& a, const BaseBlock::Lazy& b) { return !a.empty() || !b.empty(); } + }; + + class Param + { + public: + void setProvided(bool is_provided = true) + { + mIsProvided = is_provided; + enclosingBlock().paramChanged(*this, is_provided); + } + + Param& operator =(const Param& other) + { + mIsProvided = other.mIsProvided; + // don't change mEnclosingblockoffset + return *this; + } + protected: + + bool anyProvided() const { return mIsProvided; } + + Param(BaseBlock* enclosing_block); + + // store pointer to enclosing block as offset to reduce space and allow for quick copying + BaseBlock& enclosingBlock() const + { + const U8* my_addr = reinterpret_cast(this); + // get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class + return *const_cast + (reinterpret_cast + (my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset)); + } + + private: + friend class BaseBlock; + + U32 mEnclosingBlockOffset:31; + U32 mIsProvided:1; + + }; + + // these templates allow us to distinguish between template parameters + // that derive from BaseBlock and those that don't + template + struct IsBlock + { + static const bool value = false; + struct EmptyBase {}; + typedef EmptyBase base_class_t; + }; + + template + struct IsBlock + { + static const bool value = true; + typedef BaseBlock base_class_t; + }; + + template + struct IsBlock, typename T::baseblock_base_class_t > + { + static const bool value = true; + typedef BaseBlock base_class_t; + }; + + template::value> + class ParamValue : public NAME_VALUE_LOOKUP + { + public: + typedef const T& value_assignment_t; + typedef T value_t; + typedef ParamValue self_t; + + ParamValue(): mValue() {} + ParamValue(value_assignment_t other) : mValue(other) {} + + void setValue(value_assignment_t val) + { + mValue = val; + } + + value_assignment_t getValue() const + { + return mValue; + } + + T& getValue() + { + return mValue; + } + + operator value_assignment_t() const + { + return mValue; + } + + value_assignment_t operator()() const + { + return mValue; + } + + void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) + { + *this = name; + } + + self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) + { + if (NAME_VALUE_LOOKUP::getValueFromName(name, mValue)) + { + setValueName(name); + } + + return *this; + } + + protected: + T mValue; + }; + + template + class ParamValue + : public T, + public NAME_VALUE_LOOKUP + { + public: + typedef const T& value_assignment_t; + typedef T value_t; + typedef ParamValue self_t; + + ParamValue() + : T(), + mValidated(false) + {} + + ParamValue(value_assignment_t other) + : T(other), + mValidated(false) + {} + + void setValue(value_assignment_t val) + { + *this = val; + } + + value_assignment_t getValue() const + { + return *this; + } + + T& getValue() + { + return *this; + } + + operator value_assignment_t() const + { + return *this; + } + + value_assignment_t operator()() const + { + return *this; + } + + void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) + { + *this = name; + } + + self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) + { + if (NAME_VALUE_LOOKUP::getValueFromName(name, *this)) + { + setValueName(name); + } + + return *this; + } + + protected: + mutable bool mValidated; // lazy validation flag + }; + + template + class ParamValue + : public NAME_VALUE_LOOKUP + { + public: + typedef const std::string& value_assignment_t; + typedef std::string value_t; + typedef ParamValue self_t; + + ParamValue(): mValue() {} + ParamValue(value_assignment_t other) : mValue(other) {} + + void setValue(value_assignment_t val) + { + if (NAME_VALUE_LOOKUP::getValueFromName(val, mValue)) + { + NAME_VALUE_LOOKUP::setValueName(val); + } + else + { + mValue = val; + } + } + + value_assignment_t getValue() const + { + return mValue; + } + + std::string& getValue() + { + return mValue; + } + + operator value_assignment_t() const + { + return mValue; + } + + value_assignment_t operator()() const + { + return mValue; + } + + protected: + std::string mValue; + }; + + + template > + struct ParamIterator + { + typedef typename std::vector >::const_iterator const_iterator; + typedef typename std::vector >::iterator iterator; + }; + + // specialize for custom parsing/decomposition of specific classes + // e.g. TypedParam has left, top, right, bottom, etc... + template, + bool HAS_MULTIPLE_VALUES = false, + bool VALUE_IS_BLOCK = IsBlock >::value> + class TypedParam + : public Param, + public ParamValue + { + public: + typedef TypedParam self_t; + typedef ParamValue param_value_t; + typedef typename param_value_t::value_assignment_t value_assignment_t; + typedef NAME_VALUE_LOOKUP name_value_lookup_t; + + using param_value_t::operator(); + + TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + : Param(block_descriptor.mCurrentBlockPtr) + { + if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + BaseBlock::addParam(block_descriptor, param_descriptor, name); + } + + this->setValue(value); + } + + bool isProvided() const { return Param::anyProvided(); } + + static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + { + self_t& typed_param = static_cast(param); + // no further names in stack, attempt to parse value now + if (name_stack_range.first == name_stack_range.second) + { + if (parser.readValue(typed_param.getValue())) + { + typed_param.clearValueName(); + typed_param.setProvided(); + return true; + } + + // try to parse a known named value + if(name_value_lookup_t::valueNamesExist()) + { + // try to parse a known named value + std::string name; + if (parser.readValue(name)) + { + // try to parse a per type named value + if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) + { + typed_param.setValueName(name); + typed_param.setProvided(); + return true; + } + + } + } + } + return false; + } + + static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + { + const self_t& typed_param = static_cast(param); + if (!typed_param.isProvided()) return; + + if (!name_stack.empty()) + { + name_stack.back().second = true; + } + + std::string key = typed_param.getValueName(); + + // first try to write out name of name/value pair + + if (!key.empty()) + { + if (!diff_param || !ParamCompare::equals(static_cast(diff_param)->getValueName(), key)) + { + parser.writeValue(key, name_stack); + } + } + // then try to serialize value directly + else if (!diff_param || !ParamCompare::equals(typed_param.getValue(), static_cast(diff_param)->getValue())) + { + if (!parser.writeValue(typed_param.getValue(), name_stack)) + { + std::string calculated_key = typed_param.calcValueName(typed_param.getValue()); + if (!diff_param || !ParamCompare::equals(static_cast(diff_param)->getValueName(), calculated_key)) + { + parser.writeValue(calculated_key, name_stack); + } + } + } + } + + static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) + { + // tell parser about our actual type + parser.inspectValue(name_stack, min_count, max_count, NULL); + // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) + if (name_value_lookup_t::getPossibleValues()) + { + parser.inspectValue(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); + } + } + + void set(value_assignment_t val, bool flag_as_provided = true) + { + param_value_t::clearValueName(); + this->setValue(val); + setProvided(flag_as_provided); + } + + self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) + { + return static_cast(param_value_t::operator =(name)); + } + + protected: + + self_t& operator =(const self_t& other) + { + param_value_t::operator =(other); + Param::operator =(other); + return *this; + } + + static bool mergeWith(Param& dst, const Param& src, bool overwrite) + { + const self_t& src_typed_param = static_cast(src); + self_t& dst_typed_param = static_cast(dst); + + if (src_typed_param.isProvided() + && (overwrite || !dst_typed_param.isProvided())) + { + dst_typed_param.set(src_typed_param.getValue()); + return true; + } + return false; + } + }; + + // parameter that is a block + template + class TypedParam + : public Param, + public ParamValue + { + public: + typedef ParamValue param_value_t; + typedef typename param_value_t::value_assignment_t value_assignment_t; + typedef TypedParam self_t; + typedef NAME_VALUE_LOOKUP name_value_lookup_t; + + using param_value_t::operator(); + + TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + : Param(block_descriptor.mCurrentBlockPtr), + param_value_t(value) + { + if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + BaseBlock::addParam(block_descriptor, param_descriptor, name); + } + } + + static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + { + self_t& typed_param = static_cast(param); + // attempt to parse block... + if(typed_param.deserializeBlock(parser, name_stack_range, new_name)) + { + typed_param.clearValueName(); + typed_param.setProvided(); + return true; + } + + if(name_value_lookup_t::valueNamesExist()) + { + // try to parse a known named value + std::string name; + if (parser.readValue(name)) + { + // try to parse a per type named value + if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) + { + typed_param.setValueName(name); + typed_param.setProvided(); + return true; + } + + } + } + return false; + } + + static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + { + const self_t& typed_param = static_cast(param); + if (!typed_param.isProvided()) return; + + if (!name_stack.empty()) + { + name_stack.back().second = true; + } + + std::string key = typed_param.getValueName(); + if (!key.empty()) + { + if (!parser.writeValue(key, name_stack)) + { + return; + } + } + else + { + typed_param.serializeBlock(parser, name_stack, static_cast(diff_param)); + } + } + + static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) + { + // I am a param that is also a block, so just recurse into my contents + const self_t& typed_param = static_cast(param); + typed_param.inspectBlock(parser, name_stack, min_count, max_count); + } + + // a param-that-is-a-block is provided when the user has set one of its child params + // *and* the block as a whole validates + bool isProvided() const + { + // only validate block when it hasn't already passed validation with current data + if (Param::anyProvided() && !param_value_t::mValidated) + { + // a sub-block is "provided" when it has been filled in enough to be valid + param_value_t::mValidated = param_value_t::validateBlock(false); + } + return Param::anyProvided() && param_value_t::mValidated; + } + + // assign block contents to this param-that-is-a-block + void set(value_assignment_t val, bool flag_as_provided = true) + { + this->setValue(val); + param_value_t::clearValueName(); + // force revalidation of block + // next call to isProvided() will update provision status based on validity + param_value_t::mValidated = false; + setProvided(flag_as_provided); + } + + self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) + { + return static_cast(param_value_t::operator =(name)); + } + + // propagate changed status up to enclosing block + /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) + { + param_value_t::paramChanged(changed_param, user_provided); + if (user_provided) + { + // a child param has been explicitly changed + // so *some* aspect of this block is now provided + param_value_t::mValidated = false; + setProvided(); + param_value_t::clearValueName(); + } + else + { + Param::enclosingBlock().paramChanged(*this, user_provided); + } + } + + protected: + + self_t& operator =(const self_t& other) + { + param_value_t::operator =(other); + Param::operator =(other); + return *this; + } + + static bool mergeWith(Param& dst, const Param& src, bool overwrite) + { + const self_t& src_typed_param = static_cast(src); + self_t& dst_typed_param = static_cast(dst); + + if (src_typed_param.anyProvided()) + { + if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::selfBlockDescriptor(), src_typed_param, overwrite)) + { + dst_typed_param.clearValueName(); + dst_typed_param.setProvided(true); + return true; + } + } + return false; + } + }; + + // container of non-block parameters + template + class TypedParam + : public Param + { + public: + typedef TypedParam self_t; + typedef ParamValue param_value_t; + typedef typename std::vector container_t; + typedef const container_t& value_assignment_t; + + typedef typename param_value_t::value_t value_t; + typedef NAME_VALUE_LOOKUP name_value_lookup_t; + + TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + : Param(block_descriptor.mCurrentBlockPtr) + { + std::copy(value.begin(), value.end(), std::back_inserter(mValues)); + + if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + BaseBlock::addParam(block_descriptor, param_descriptor, name); + } + } + + bool isProvided() const { return Param::anyProvided(); } + + static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + { + self_t& typed_param = static_cast(param); + value_t value; + // no further names in stack, attempt to parse value now + if (name_stack_range.first == name_stack_range.second) + { + // attempt to read value directly + if (parser.readValue(value)) + { + typed_param.add(value); + return true; + } + + // try to parse a known named value + if(name_value_lookup_t::valueNamesExist()) + { + // try to parse a known named value + std::string name; + if (parser.readValue(name)) + { + // try to parse a per type named value + if (name_value_lookup_t::getValueFromName(name, value)) + { + typed_param.add(value); + typed_param.mValues.back().setValueName(name); + return true; + } + + } + } + } + return false; + } + + static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + { + const self_t& typed_param = static_cast(param); + if (!typed_param.isProvided() || name_stack.empty()) return; + + for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); + it != end_it; + ++it) + { + std::string key = it->getValueName(); + name_stack.back().second = true; + + if(key.empty()) + // not parsed via name values, write out value directly + { + bool value_written = parser.writeValue(*it, name_stack); + if (!value_written) + { + std::string calculated_key = it->calcValueName(it->getValue()); + if (!parser.writeValue(calculated_key, name_stack)) + { + break; + } + } + } + else + { + if(!parser.writeValue(key, name_stack)) + { + break; + } + } + } + } + + static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) + { + parser.inspectValue(name_stack, min_count, max_count, NULL); + if (name_value_lookup_t::getPossibleValues()) + { + parser.inspectValue(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); + } + } + + void set(value_assignment_t val, bool flag_as_provided = true) + { + mValues = val; + setProvided(flag_as_provided); + } + + param_value_t& add() + { + mValues.push_back(param_value_t(value_t())); + Param::setProvided(); + return mValues.back(); + } + + void add(const value_t& item) + { + param_value_t param_value; + param_value.setValue(item); + mValues.push_back(param_value); + setProvided(); + } + + void add(const typename name_value_lookup_t::name_t& name) + { + value_t value; + + // try to parse a per type named value + if (name_value_lookup_t::getValueFromName(name, value)) + { + add(value); + mValues.back().setValueName(name); + } + } + + // implicit conversion + operator value_assignment_t() const { return mValues; } + // explicit conversion + value_assignment_t operator()() const { return mValues; } + + typedef typename container_t::iterator iterator; + typedef typename container_t::const_iterator const_iterator; + iterator begin() { return mValues.begin(); } + iterator end() { return mValues.end(); } + const_iterator begin() const { return mValues.begin(); } + const_iterator end() const { return mValues.end(); } + bool empty() const { return mValues.empty(); } + size_t size() const { return mValues.size(); } + + U32 numValidElements() const + { + return mValues.size(); + } + + protected: + static bool mergeWith(Param& dst, const Param& src, bool overwrite) + { + const self_t& src_typed_param = static_cast(src); + self_t& dst_typed_param = static_cast(dst); + + if (overwrite) + { + std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues)); + } + else + { + container_t new_values(src_typed_param.mValues); + std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values)); + std::swap(dst_typed_param.mValues, new_values); + } + + if (src_typed_param.begin() != src_typed_param.end()) + { + dst_typed_param.setProvided(); + } + return true; + } + + container_t mValues; + }; + + // container of block parameters + template + class TypedParam + : public Param + { + public: + typedef TypedParam self_t; + typedef ParamValue param_value_t; + typedef typename std::vector container_t; + typedef const container_t& value_assignment_t; + typedef typename param_value_t::value_t value_t; + typedef NAME_VALUE_LOOKUP name_value_lookup_t; + + TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + : Param(block_descriptor.mCurrentBlockPtr) + { + std::copy(value.begin(), value.end(), back_inserter(mValues)); + + if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + BaseBlock::addParam(block_descriptor, param_descriptor, name); + } + } + + bool isProvided() const { return Param::anyProvided(); } + + static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + { + self_t& typed_param = static_cast(param); + bool new_value = false; + + if (new_name || typed_param.mValues.empty()) + { + new_value = true; + typed_param.mValues.push_back(value_t()); + } + + param_value_t& value = typed_param.mValues.back(); + + // attempt to parse block... + if(value.deserializeBlock(parser, name_stack_range, new_name)) + { + typed_param.setProvided(); + return true; + } + else if(name_value_lookup_t::valueNamesExist()) + { + // try to parse a known named value + std::string name; + if (parser.readValue(name)) + { + // try to parse a per type named value + if (name_value_lookup_t::getValueFromName(name, value.getValue())) + { + typed_param.mValues.back().setValueName(name); + typed_param.setProvided(); + return true; + } + + } + } + + if (new_value) + { // failed to parse new value, pop it off + typed_param.mValues.pop_back(); + } + + return false; + } + + static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + { + const self_t& typed_param = static_cast(param); + if (!typed_param.isProvided() || name_stack.empty()) return; + + for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); + it != end_it; + ++it) + { + name_stack.back().second = true; + + std::string key = it->getValueName(); + if (!key.empty()) + { + parser.writeValue(key, name_stack); + } + // Not parsed via named values, write out value directly + // NOTE: currently we don't worry about removing default values in Multiple + else + { + it->serializeBlock(parser, name_stack, NULL); + } + } + } + + static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) + { + // I am a vector of blocks, so describe my contents recursively + param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count); + } + + void set(value_assignment_t val, bool flag_as_provided = true) + { + mValues = val; + setProvided(flag_as_provided); + } + + param_value_t& add() + { + mValues.push_back(value_t()); + setProvided(); + return mValues.back(); + } + + void add(const value_t& item) + { + mValues.push_back(item); + setProvided(); + } + + void add(const typename name_value_lookup_t::name_t& name) + { + value_t value; + + // try to parse a per type named value + if (name_value_lookup_t::getValueFromName(name, value)) + { + add(value); + mValues.back().setValueName(name); + } + } + + // implicit conversion + operator value_assignment_t() const { return mValues; } + // explicit conversion + value_assignment_t operator()() const { return mValues; } + + typedef typename container_t::iterator iterator; + typedef typename container_t::const_iterator const_iterator; + iterator begin() { return mValues.begin(); } + iterator end() { return mValues.end(); } + const_iterator begin() const { return mValues.begin(); } + const_iterator end() const { return mValues.end(); } + bool empty() const { return mValues.empty(); } + size_t size() const { return mValues.size(); } + + U32 numValidElements() const + { + U32 count = 0; + for (const_iterator it = mValues.begin(), end_it = mValues.end(); + it != end_it; + ++it) + { + if(it->validateBlock(false)) count++; + } + return count; + } + + protected: + + static bool mergeWith(Param& dst, const Param& src, bool overwrite) + { + const self_t& src_typed_param = static_cast(src); + self_t& dst_typed_param = static_cast(dst); + + if (overwrite) + { + std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues)); + } + else + { + container_t new_values(src_typed_param.mValues); + std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values)); + std::swap(dst_typed_param.mValues, new_values); + } + + if (src_typed_param.begin() != src_typed_param.end()) + { + dst_typed_param.setProvided(); + } + + return true; + } + + container_t mValues; + }; + + template + class ChoiceBlock : public BASE_BLOCK + { + typedef ChoiceBlock self_t; + typedef ChoiceBlock enclosing_block_t; + typedef BASE_BLOCK base_block_t; + + LOG_CLASS(self_t); + public: + // take all provided params from other and apply to self + bool overwriteFrom(const self_t& other) + { + return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, true); + } + + // take all provided params that are not already provided, and apply to self + bool fillFrom(const self_t& other) + { + return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, false); + } + + bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) + { + bool source_override = source_provided && (overwrite || !dest_provided); + + if (source_override || source.mCurChoice == mCurChoice) + { + return mergeBlock(block_data, source, overwrite); + } + return false; + } + + // merge with other block + bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite) + { + mCurChoice = other.mCurChoice; + return base_block_t::mergeBlock(selfBlockDescriptor(), other, overwrite); + } + + // clear out old choice when param has changed + /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) + { + param_handle_t changed_param_handle = base_block_t::getHandleFromParam(&changed_param); + // if we have a new choice... + if (changed_param_handle != mCurChoice) + { + // clear provided flag on previous choice + Param* previous_choice = base_block_t::getParamFromHandle(mCurChoice); + if (previous_choice) + { + previous_choice->setProvided(false); + } + mCurChoice = changed_param_handle; + } + base_block_t::paramChanged(changed_param, user_provided); + } + + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + + protected: + ChoiceBlock() + : mCurChoice(0) + { + BaseBlock::init(selfBlockDescriptor(), base_block_t::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); + } + + // Alternatives are mutually exclusive wrt other Alternatives in the same block. + // One alternative in a block will always have isChosen() == true. + // At most one alternative in a block will have isProvided() == true. + template > + class Alternative : public TypedParam + { + public: + friend class ChoiceBlock; + + typedef Alternative self_t; + typedef TypedParam >::value> super_t; + typedef typename super_t::value_assignment_t value_assignment_t; + + using super_t::operator =; + + explicit Alternative(const char* name = "", value_assignment_t val = defaultValue()) + : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1), + mOriginalValue(val) + { + // assign initial choice to first declared option + DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr); + if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) + { + if(blockp->mCurChoice == 0) + { + blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this); + } + } + } + + void choose() + { + static_cast(Param::enclosingBlock()).paramChanged(*this, true); + } + + void chooseAs(value_assignment_t val) + { + super_t::set(val); + } + + void operator =(value_assignment_t val) + { + super_t::set(val); + } + + void operator()(typename super_t::value_assignment_t val) + { + super_t::set(val); + } + + operator value_assignment_t() const + { + return (*this)(); + } + + value_assignment_t operator()() const + { + if (static_cast(Param::enclosingBlock()).getCurrentChoice() == this) + { + return super_t::getValue(); + } + return mOriginalValue; + } + + bool isChosen() const + { + return static_cast(Param::enclosingBlock()).getCurrentChoice() == this; + } + + private: + T mOriginalValue; + }; + + protected: + static BlockDescriptor& selfBlockDescriptor() + { + static BlockDescriptor sBlockDescriptor; + return sBlockDescriptor; + } + + private: + param_handle_t mCurChoice; + + const Param* getCurrentChoice() const + { + return base_block_t::getParamFromHandle(mCurChoice); + } + }; + + template + class Block + : public BASE_BLOCK + { + typedef Block self_t; + typedef Block block_t; + + public: + typedef BASE_BLOCK base_block_t; + + // take all provided params from other and apply to self + bool overwriteFrom(const self_t& other) + { + return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, true); + } + + // take all provided params that are not already provided, and apply to self + bool fillFrom(const self_t& other) + { + return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, false); + } + + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + + protected: + Block() + { + //#pragma message("Parsing LLInitParam::Block") + BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); + } + + // + // Nested classes for declaring parameters + // + template > + class Optional : public TypedParam + { + public: + typedef TypedParam >::value> super_t; + typedef typename super_t::value_assignment_t value_assignment_t; + + using super_t::operator(); + using super_t::operator =; + + explicit Optional(const char* name = "", value_assignment_t val = defaultValue()) + : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1) + { + //#pragma message("Parsing LLInitParam::Block::Optional") + } + + Optional& operator =(value_assignment_t val) + { + this->set(val); + return *this; + } + + DERIVED_BLOCK& operator()(value_assignment_t val) + { + super_t::set(val); + return static_cast(Param::enclosingBlock()); + } + }; + + template > + class Mandatory : public TypedParam + { + public: + typedef TypedParam >::value> super_t; + typedef Mandatory self_t; + typedef typename super_t::value_assignment_t value_assignment_t; + + using super_t::operator(); + using super_t::operator =; + + // mandatory parameters require a name to be parseable + explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue()) + : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1) + {} + + Mandatory& operator =(value_assignment_t val) + { + this->set(val); + return *this; + } + + DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) + { + super_t::set(val); + return static_cast(Param::enclosingBlock()); + } + + static bool validate(const Param* p) + { + // valid only if provided + return static_cast(p)->isProvided(); + } + + }; + + template > + class Multiple : public TypedParam + { + public: + typedef TypedParam >::value> super_t; + typedef Multiple self_t; + typedef typename super_t::container_t container_t; + typedef typename super_t::value_assignment_t value_assignment_t; + typedef typename super_t::iterator iterator; + typedef typename super_t::const_iterator const_iterator; + + explicit Multiple(const char* name = "") + : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) + {} + + Multiple& operator =(value_assignment_t val) + { + set(val); + return *this; + } + + DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) + { + super_t::set(val); + return static_cast(Param::enclosingBlock()); + } + + static bool validate(const Param* paramp) + { + U32 num_valid = ((super_t*)paramp)->numValidElements(); + return RANGE::minCount <= num_valid && num_valid <= RANGE::maxCount; + } + }; + + class Deprecated : public Param + { + public: + explicit Deprecated(const char* name) + : Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr) + { + BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); + if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + NULL, + &deserializeParam, + NULL, + NULL, + NULL, + 0, S32_MAX)); + BaseBlock::addParam(block_descriptor, param_descriptor, name); + } + } + + static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + { + if (name_stack_range.first == name_stack_range.second) + { + //std::string message = llformat("Deprecated value %s ignored", getName().c_str()); + //parser.parserWarning(message); + return true; + } + + return false; + } + }; + + // different semantics for documentation purposes, but functionally identical + typedef Deprecated Ignored; + + protected: + static BlockDescriptor& selfBlockDescriptor() + { + static BlockDescriptor sBlockDescriptor; + return sBlockDescriptor; + } + + template + void changeDefault(TypedParam& param, + typename TypedParam::value_assignment_t value) + { + if (!param.isProvided()) + { + param.set(value, false); + } + } + + }; + + template + class BatchBlock + : public Block + { + public: + typedef BatchBlock self_t; + typedef Block super_t; + + BatchBlock() + {} + + bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) + { + if (new_name) + { + // reset block + *static_cast(this) = defaultBatchValue(); + } + return super_t::deserializeBlock(p, name_stack_range, new_name); + } + + bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) + { + if (overwrite) + { + *static_cast(this) = defaultBatchValue(); + // merge individual parameters into destination + return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite); + } + return false; + } + protected: + static const DERIVED_BLOCK& defaultBatchValue() + { + static DERIVED_BLOCK default_value; + return default_value; + } + }; + + // FIXME: this specialization is not currently used, as it only matches against the BatchBlock base class + // and not the derived class with the actual params + template + class ParamValue , + NAME_VALUE_LOOKUP, + true> + : public NAME_VALUE_LOOKUP, + protected BatchBlock + { + public: + typedef BatchBlock block_t; + typedef const BatchBlock& value_assignment_t; + typedef block_t value_t; + + ParamValue() + : block_t(), + mValidated(false) + {} + + ParamValue(value_assignment_t other) + : block_t(other), + mValidated(false) + { + } + + void setValue(value_assignment_t val) + { + *this = val; + } + + value_assignment_t getValue() const + { + return *this; + } + + BatchBlock& getValue() + { + return *this; + } + + operator value_assignment_t() const + { + return *this; + } + + value_assignment_t operator()() const + { + return *this; + } + + protected: + mutable bool mValidated; // lazy validation flag + }; + + template + class ParamValue , + TypeValues, + IS_BLOCK> + : public IsBlock::base_class_t + { + public: + typedef ParamValue , TypeValues, false> self_t; + typedef const T& value_assignment_t; + typedef T value_t; + + ParamValue() + : mValue(), + mValidated(false) + {} + + ParamValue(value_assignment_t other) + : mValue(other), + mValidated(false) + {} + + void setValue(value_assignment_t val) + { + mValue.set(val); + } + + value_assignment_t getValue() const + { + return mValue.get(); + } + + T& getValue() + { + return mValue.get(); + } + + operator value_assignment_t() const + { + return mValue.get(); + } + + value_assignment_t operator()() const + { + return mValue.get(); + } + + bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) + { + return mValue.get().deserializeBlock(p, name_stack_range, new_name); + } + + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const + { + if (mValue.empty()) return; + + mValue.get().serializeBlock(p, name_stack, diff_block); + } + + bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const + { + if (mValue.empty()) return false; + + return mValue.get().inspectBlock(p, name_stack, min_count, max_count); + } + + protected: + mutable bool mValidated; // lazy validation flag + + private: + BaseBlock::Lazy mValue; + }; + + template <> + class ParamValue , + false> + : public TypeValues, + public BaseBlock + { + public: + typedef ParamValue, false> self_t; + typedef const LLSD& value_assignment_t; + + ParamValue() + : mValidated(false) + {} + + ParamValue(value_assignment_t other) + : mValue(other), + mValidated(false) + {} + + void setValue(value_assignment_t val) { mValue = val; } + + value_assignment_t getValue() const { return mValue; } + LLSD& getValue() { return mValue; } + + operator value_assignment_t() const { return mValue; } + value_assignment_t operator()() const { return mValue; } + + + // block param interface + bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; + bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const + { + //TODO: implement LLSD params as schema type Any + return true; + } + + protected: + mutable bool mValidated; // lazy validation flag + + private: + static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack); + + LLSD mValue; + }; + + template + class CustomParamValue + : public Block > >, + public TypeValues + { + public: + typedef enum e_value_age + { + VALUE_NEEDS_UPDATE, // mValue needs to be refreshed from the block parameters + VALUE_AUTHORITATIVE, // mValue holds the authoritative value (which has been replicated to the block parameters via updateBlockFromValue) + BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative + } EValueAge; + + typedef ParamValue > derived_t; + typedef CustomParamValue self_t; + typedef Block block_t; + typedef const T& value_assignment_t; + typedef T value_t; + + + CustomParamValue(const T& value = T()) + : mValue(value), + mValueAge(VALUE_AUTHORITATIVE), + mValidated(false) + {} + + bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name) + { + derived_t& typed_param = static_cast(*this); + // try to parse direct value T + if (name_stack_range.first == name_stack_range.second) + { + if(parser.readValue(typed_param.mValue)) + { + typed_param.mValueAge = VALUE_AUTHORITATIVE; + typed_param.updateBlockFromValue(false); + + typed_param.clearValueName(); + + return true; + } + } + + // fall back on parsing block components for T + return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name); + } + + void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const + { + const derived_t& typed_param = static_cast(*this); + const derived_t* diff_param = static_cast(diff_block); + + std::string key = typed_param.getValueName(); + + // first try to write out name of name/value pair + if (!key.empty()) + { + if (!diff_param || !ParamCompare::equals(diff_param->getValueName(), key)) + { + parser.writeValue(key, name_stack); + } + } + // then try to serialize value directly + else if (!diff_param || !ParamCompare::equals(typed_param.getValue(), diff_param->getValue())) + { + + if (!parser.writeValue(typed_param.getValue(), name_stack)) + { + //RN: *always* serialize provided components of BlockValue (don't pass diff_param on), + // since these tend to be viewed as the constructor arguments for the value T. It seems + // cleaner to treat the uniqueness of a BlockValue according to the generated value, and + // not the individual components. This way will not + // be exported as , since it was probably the intent of the user to + // be specific about the RGB color values. This also fixes an issue where we distinguish + // between rect.left not being provided and rect.left being explicitly set to 0 (same as default) + + if (typed_param.mValueAge == VALUE_AUTHORITATIVE) + { + // if the value is authoritative but the parser doesn't accept the value type + // go ahead and make a copy, and splat the value out to its component params + // and serialize those params + derived_t copy(typed_param); + copy.updateBlockFromValue(true); + copy.block_t::serializeBlock(parser, name_stack, NULL); + } + else + { + block_t::serializeBlock(parser, name_stack, NULL); + } + } + } + } + + bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const + { + // first, inspect with actual type... + parser.inspectValue(name_stack, min_count, max_count, NULL); + if (TypeValues::getPossibleValues()) + { + //...then inspect with possible string values... + parser.inspectValue(name_stack, min_count, max_count, TypeValues::getPossibleValues()); + } + // then recursively inspect contents... + return block_t::inspectBlock(parser, name_stack, min_count, max_count); + } + + bool validateBlock(bool emit_errors = true) const + { + if (mValueAge == VALUE_NEEDS_UPDATE) + { + if (block_t::validateBlock(emit_errors)) + { + // clear stale keyword associated with old value + TypeValues::clearValueName(); + mValueAge = BLOCK_AUTHORITATIVE; + static_cast(const_cast(this))->updateValueFromBlock(); + return true; + } + else + { + //block value incomplete, so not considered provided + // will attempt to revalidate on next call to isProvided() + return false; + } + } + else + { + // we have a valid value in hand + return true; + } + } + + // propagate change status up to enclosing block + /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) + { + BaseBlock::paramChanged(changed_param, user_provided); + if (user_provided) + { + // a parameter changed, so our value is out of date + mValueAge = VALUE_NEEDS_UPDATE; + } + } + + void setValue(value_assignment_t val) + { + derived_t& typed_param = static_cast(*this); + // set param version number to be up to date, so we ignore block contents + mValueAge = VALUE_AUTHORITATIVE; + mValue = val; + typed_param.clearValueName(); + static_cast(this)->updateBlockFromValue(false); + } + + value_assignment_t getValue() const + { + validateBlock(true); + return mValue; + } + + T& getValue() + { + validateBlock(true); + return mValue; + } + + operator value_assignment_t() const + { + return getValue(); + } + + value_assignment_t operator()() const + { + return getValue(); + } + + protected: + + // use this from within updateValueFromBlock() to set the value without making it authoritative + void updateValue(value_assignment_t value) + { + mValue = value; + } + + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite) + { + bool source_override = source_provided && (overwrite || !dst_provided); + + const derived_t& src_typed_param = static_cast(source); + + if (source_override && src_typed_param.mValueAge == VALUE_AUTHORITATIVE) + { + // copy value over + setValue(src_typed_param.getValue()); + return true; + } + // merge individual parameters into destination + if (mValueAge == VALUE_AUTHORITATIVE) + { + static_cast(this)->updateBlockFromValue(dst_provided); + } + return mergeBlock(block_data, source, overwrite); + } + + bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& source, bool overwrite) + { + return block_t::mergeBlock(block_data, source, overwrite); + } + + mutable bool mValidated; // lazy validation flag + + private: + mutable T mValue; + mutable EValueAge mValueAge; + }; +} + + +#endif // LL_LLPARAM_H diff --git a/indra/llxuixml/lluicolor.cpp b/indra/llxuixml/lluicolor.cpp new file mode 100644 index 000000000..f9bb80f8c --- /dev/null +++ b/indra/llxuixml/lluicolor.cpp @@ -0,0 +1,87 @@ +/** + * @file lluicolor.cpp + * @brief brief LLUIColor class implementation file + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lluicolor.h" + +LLUIColor::LLUIColor() + :mColorPtr(NULL) +{ +} + + +LLUIColor::LLUIColor(const LLColor4& color) +: mColor(color), + mColorPtr(NULL) +{ +} + +LLUIColor::LLUIColor(const LLUIColor* color) +: mColorPtr(color) +{ +} + +void LLUIColor::set(const LLColor4& color) +{ + mColor = color; + mColorPtr = NULL; +} + +void LLUIColor::set(const LLUIColor* color) +{ + mColorPtr = color; +} + +const LLColor4& LLUIColor::get() const +{ + return (mColorPtr == NULL ? mColor : mColorPtr->get()); +} + +LLUIColor::operator const LLColor4& () const +{ + return get(); +} + +const LLColor4& LLUIColor::operator()() const +{ + return get(); +} + +bool LLUIColor::isReference() const +{ + return mColorPtr != NULL; +} + +namespace LLInitParam +{ + // used to detect equivalence with default values on export + bool ParamCompare::equals(const LLUIColor &a, const LLUIColor &b) + { + // do not detect value equivalence, treat pointers to colors as distinct from color values + return (a.mColorPtr == NULL && b.mColorPtr == NULL ? a.mColor == b.mColor : a.mColorPtr == b.mColorPtr); + } +} diff --git a/indra/llxuixml/lluicolor.h b/indra/llxuixml/lluicolor.h new file mode 100644 index 000000000..97ebea854 --- /dev/null +++ b/indra/llxuixml/lluicolor.h @@ -0,0 +1,71 @@ +/** + * @file lluicolor.h + * @brief brief LLUIColor class header file + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLUICOLOR_H_ +#define LL_LLUICOLOR_H_ + +#include "v4color.h" + +namespace LLInitParam +{ + template + struct ParamCompare; +} + +class LLUIColor +{ +public: + LLUIColor(); + LLUIColor(const LLColor4& color); + LLUIColor(const LLUIColor* color); + + void set(const LLColor4& color); + void set(const LLUIColor* color); + + const LLColor4& get() const; + + operator const LLColor4& () const; + const LLColor4& operator()() const; + + bool isReference() const; + +private: + friend struct LLInitParam::ParamCompare; + + const LLUIColor* mColorPtr; + LLColor4 mColor; +}; + +namespace LLInitParam +{ + template<> + struct ParamCompare + { + static bool equals(const LLUIColor& a, const LLUIColor& b); + }; +} + +#endif diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h index a54ebd583..bf810817b 100644 --- a/indra/lscript/lscript_byteformat.h +++ b/indra/lscript/lscript_byteformat.h @@ -535,6 +535,7 @@ typedef enum e_lscript_runtime_permissions SCRIPT_PERMISSION_CHANGE_PERMISSIONS, SCRIPT_PERMISSION_TRACK_CAMERA, SCRIPT_PERMISSION_CONTROL_CAMERA, + SCRIPT_PERMISSION_TELEPORT, SCRIPT_PERMISSION_EOF } LSCRIPTRunTimePermissions; @@ -551,6 +552,7 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] = (0x1 << 9), // SCRIPT_PERMISSION_CHANGE_PERMISSIONS (0x1 << 10),// SCRIPT_PERMISSION_TRACK_CAMERA (0x1 << 11),// SCRIPT_PERMISSION_CONTROL_CAMERA + (0x1 << 12),// SCRIPT_PERMISSION_TELEPORT }; // http_request string constants diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l index 2235dc134..aeb976399 100644 --- a/indra/lscript/lscript_compile/indra.l +++ b/indra/lscript/lscript_compile/indra.l @@ -1,3 +1,4 @@ + N [0-9] L [a-zA-Z_] H [a-fA-F0-9] @@ -211,7 +212,8 @@ extern "C" { int yyerror(const char *fmt, ...); } "PERMISSION_CHANGE_JOINTS" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_CHANGE_JOINTS]; return(INTEGER_CONSTANT); } "PERMISSION_CHANGE_PERMISSIONS" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_CHANGE_PERMISSIONS]; return(INTEGER_CONSTANT); } "PERMISSION_TRACK_CAMERA" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TRACK_CAMERA]; return(INTEGER_CONSTANT); } -"PERMISSION_CONTROL_CAMERA" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_CONTROL_CAMERA]; return(INTEGER_CONSTANT); } +"PERMISSION_CONTROL_CAMERA" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_CONTROL_CAMERA]; return(INTEGER_CONSTANT); } +"PERMISSION_TELEPORT" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TELEPORT]; return(INTEGER_CONSTANT); } "INVENTORY_TEXTURE" { count(); yylval.ival = LLAssetType::AT_TEXTURE; return(INTEGER_CONSTANT); } "INVENTORY_SOUND" { count(); yylval.ival = LLAssetType::AT_SOUND; return(INTEGER_CONSTANT); } @@ -307,8 +309,8 @@ extern "C" { int yyerror(const char *fmt, ...); } "ATTACH_LULEG" { count(); yylval.ival = 26; return(INTEGER_CONSTANT); } "ATTACH_LLLEG" { count(); yylval.ival = 27; return(INTEGER_CONSTANT); } "ATTACH_BELLY" { count(); yylval.ival = 28; return(INTEGER_CONSTANT); } -"ATTACH_LPEC" { count(); yylval.ival = 29; return(INTEGER_CONSTANT); } -"ATTACH_RPEC" { count(); yylval.ival = 30; return(INTEGER_CONSTANT); } +"ATTACH_RPEC" { count(); yylval.ival = 29; return(INTEGER_CONSTANT); } +"ATTACH_LPEC" { count(); yylval.ival = 30; return(INTEGER_CONSTANT); } "ATTACH_HUD_CENTER_2" { count(); yylval.ival = 31; return(INTEGER_CONSTANT); } "ATTACH_HUD_TOP_RIGHT" { count(); yylval.ival = 32; return(INTEGER_CONSTANT); } "ATTACH_HUD_TOP_CENTER" { count(); yylval.ival = 33; return(INTEGER_CONSTANT); } diff --git a/indra/lscript/lscript_execute/llscriptresource.cpp b/indra/lscript/lscript_execute/llscriptresource.cpp index 05ab8ebba..cd3696ab3 100644 --- a/indra/lscript/lscript_execute/llscriptresource.cpp +++ b/indra/lscript/lscript_execute/llscriptresource.cpp @@ -31,6 +31,7 @@ */ #include "linden_common.h" + #include "llscriptresource.h" #include "llerror.h" diff --git a/indra/lscript/lscript_library/lscript_library.cpp b/indra/lscript/lscript_library/lscript_library.cpp index 919fb758c..b4a708f87 100644 --- a/indra/lscript/lscript_library/lscript_library.cpp +++ b/indra/lscript/lscript_library/lscript_library.cpp @@ -461,11 +461,12 @@ void LLScriptLibrary::init() addFunction(10.f, 0.f, dummy_func, "llGetLinkNumberOfSides", "i", "i"); - // IDEVO Name lookup calls, see lscript_avatar_names.h + // IDEVO Name lookup calls, see lscript_avatar_names.h addFunction(10.f, 0.f, dummy_func, "llGetUsername", "s", "k"); addFunction(10.f, 0.f, dummy_func, "llRequestUsername", "k", "k"); addFunction(10.f, 0.f, dummy_func, "llGetDisplayName", "s", "k"); addFunction(10.f, 0.f, dummy_func, "llRequestDisplayName", "k", "k"); + addFunction(10.f, 0.f, dummy_func, "llGetEnv", "s", "s"); addFunction(10.f, 0.f, dummy_func, "llRegionSayTo", NULL, "kis"); @@ -487,10 +488,34 @@ void LLScriptLibrary::init() addFunction(10.f, 0.f, dummy_func, "llSetContentType", NULL, "ki"); addFunction(10.f, 0.f, dummy_func, "llLinkSitTarget", NULL, "ivr"); addFunction(10.f, 0.f, dummy_func, "llAvatarOnLinkSitTarget", "k", "i"); - /* No info on these new functions yet.... - * addFunction(10.f, 0.f, dummy_func, "llSetVelocity", "", ""); - * addFunction(10.f, 0.f, dummy_func, "llSetRotationalVelocity", "", ""); - */ + addFunction(10.f, 0.f, dummy_func, "llGetMassMKS", "f", NULL); + addFunction(10.f, 0.f, dummy_func, "llGetMemoryLimit", "i", NULL); + addFunction(10.f, 0.f, dummy_func, "llGetParcelMusicURL", "s", NULL); + addFunction(10.f, 0.f, dummy_func, "llGetPhysicsMaterial", "l", NULL); + addFunction(10.f, 0.f, dummy_func, "llManageEstateAccess", "i", "ik"); + addFunction(10.f, 0.f, dummy_func, "llSetAngularVelocity", NULL, "vi"); + addFunction(10.f, 0.f, dummy_func, "llSetKeyframedMotion", NULL, "ll"); + addFunction(10.f, 0.f, dummy_func, "llSetPhysicsMaterial", NULL, "iffff"); + addFunction(10.f, 0.f, dummy_func, "llSetRegionPos", "i", "v"); + addFunction(10.f, 0.f, dummy_func, "llSetVelocity", NULL, "vi"); + addFunction(10.f, 0.f, dummy_func, "llTransferLindenDollars", "k", "ki"); + + + //Pathfinder functions. Current state: alpha, thus subject to change. + //This and the preceding line are to be removed in future revisions of this file. + addFunction(10.f, 0.f, dummy_func, "llCreateCharacter", NULL, "l"); + addFunction(10.f, 0.f, dummy_func, "llDeleteCharacter", NULL, NULL); + addFunction(10.f, 0.f, dummy_func, "llEvade", NULL, "kl"); + addFunction(10.f, 0.f, dummy_func, "llExecCharacterCmd", NULL, "il"); + addFunction(10.f, 0.f, dummy_func, "llGetClosestNavPoint", "l", "vl"); + addFunction(10.f, 0.f, dummy_func, "llFleeFrom", NULL, "vfl"); + addFunction(10.f, 0.f, dummy_func, "llNavigateTo", NULL, "vl"); + addFunction(10.f, 0.f, dummy_func, "llPatrolPoints", NULL, "ll"); + addFunction(10.f, 0.f, dummy_func, "llPursue", NULL, "kl"); + addFunction(10.f, 0.f, dummy_func, "llUpdateCharacter", NULL, "l"); + addFunction(10.f, 0.f, dummy_func, "llWanderWithin", NULL, "vfl"); + + // REGARDING OSSL FUNCTIONS // These additions should be posted underneath the llFunctions @@ -624,6 +649,16 @@ void LLScriptLibrary::init() addFunction(10.f, 0.f, dummy_func, "osNpcGetPos", "v", "k"); addFunction(10.f, 0.f, dummy_func, "osNpcStopMoveToTarget", NULL, "k"); + addFunction(10.f, 0.f, dummy_func, "osIsNpc", "i", "k"); + addFunction(10.f, 0.f, dummy_func, "osNpcGetOwner", "k", "k"); + addFunction(10.f, 0.f, dummy_func, "osGetGridCustom", "s", "s"); + addFunction(10.f, 0.f, dummy_func, "osGetGridHomeURI", "s", NULL); + addFunction(10.f, 0.f, dummy_func, "osNpcPlayAnimation", NULL, "ks"); + addFunction(10.f, 0.f, dummy_func, "osNpcSit", NULL, "kki"); + addFunction(10.f, 0.f, dummy_func, "osNpcStand", NULL, "k"); + addFunction(10.f, 0.f, dummy_func, "osNpcStopAnimation", NULL, "ks"); + addFunction(10.f, 0.f, dummy_func, "osSetRot", NULL, "kq"); + } LLScriptLibraryFunction::LLScriptLibraryFunction(F32 eu, F32 st, void (*exec_func)(LLScriptLibData *, LLScriptLibData *, const LLUUID &), const char *name, const char *ret_type, const char *args, BOOL god_only) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e28151f62..bd27204b6 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -17,7 +17,7 @@ if(NOT FMODEX) include(FMOD) endif(NOT FMODEX) include(OPENAL) -include(HUNSPELL) +include(Hunspell) include(FindOpenGL) #include(JsonCpp) include(LLAddBuildTest) @@ -37,6 +37,7 @@ include(LLUI) include(LLVFS) include(LLWindow) include(LLXML) +include(LLXUIXML) include(LScript) include(Linking) include(NDOF) @@ -71,6 +72,7 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} + ${LLXUIXML_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS}/lscript_compile ) @@ -86,7 +88,6 @@ set(viewer_SOURCE_FILES lggdicdownload.cpp floaterao.cpp floatervoicelicense.cpp - cofmgr.cpp lldaycyclemanager.cpp llenvmanager.cpp llwlhandlers.cpp @@ -97,8 +98,8 @@ set(viewer_SOURCE_FILES ascentprefschat.cpp ascentprefssys.cpp ascentprefsvan.cpp - dhparam.cpp - dsaparam.cpp + #dhparam.cpp + #dsaparam.cpp emeraldboobutils.cpp dofloaterhex.cpp dohexeditor.cpp @@ -110,6 +111,7 @@ set(viewer_SOURCE_FILES hippolimits.cpp hipporestrequest.cpp hippopanelgrids.cpp + importtracker.cpp jcfloaterareasearch.cpp chatbar_as_cmdline.cpp qtoolalign.cpp @@ -122,7 +124,9 @@ set(viewer_SOURCE_FILES llagentpilot.cpp llagentui.cpp llagentwearables.cpp + llagentwearablesfetch.cpp llanimstatelabels.cpp + llappearancemgr.cpp llappviewer.cpp llassetconverter.cpp llassetuploadresponders.cpp @@ -144,7 +148,6 @@ set(viewer_SOURCE_FILES llcolorswatch.cpp llcommandhandler.cpp llcommandlineparser.cpp - llcompass.cpp llcompilequeue.cpp llconfirmationmanager.cpp llconsole.cpp @@ -167,6 +170,7 @@ set(viewer_SOURCE_FILES lldrawpoolwater.cpp lldrawpoolwlsky.cpp lldriverparam.cpp + lldroptarget.cpp lldynamictexture.cpp llemote.cpp lleventinfo.cpp @@ -308,14 +312,17 @@ set(viewer_SOURCE_FILES llinventorypanel.cpp lljoystickbutton.cpp lllandmarklist.cpp + lllocaltextureobject.cpp lllocalinventory.cpp lllogchat.cpp llloginhandler.cpp llsavedlogins.cpp + llmainlooprepeater.cpp llmanip.cpp llmaniprotate.cpp llmanipscale.cpp llmaniptranslate.cpp + llmarketplacenotifications.cpp llmediaremotectrl.cpp llmemoryview.cpp llmenucommands.cpp @@ -329,12 +336,14 @@ set(viewer_SOURCE_FILES llnamelistctrl.cpp llnetmap.cpp llnotify.cpp + lloutfitobserver.cpp lloverlaybar.cpp llpanelaudioprefs.cpp llpanelaudiovolume.cpp llpanelavatar.cpp llpanelclassified.cpp llpanelcontents.cpp + llpaneleditwearable.cpp llpaneldebug.cpp llpaneldirbrowser.cpp llpaneldirclassified.cpp @@ -357,7 +366,7 @@ set(viewer_SOURCE_FILES llpanelgrouproles.cpp llpanelgroupvoting.cpp llpanelinput.cpp - llpanelinventory.cpp + llpanelobjectinventory.cpp llpanelland.cpp llpanellandaudio.cpp llpanellandmedia.cpp @@ -398,6 +407,8 @@ set(viewer_SOURCE_FILES llregionposition.cpp llremoteparcelrequest.cpp llsavedsettingsglue.cpp + llscrollingpanelparam.cpp + llscrollingpanelparambase.cpp llselectmgr.cpp llsky.cpp llspatialpartition.cpp @@ -411,7 +422,9 @@ set(viewer_SOURCE_FILES llstylemap.cpp llsurface.cpp llsurfacepatch.cpp + lltexglobalcolor.cpp lltexlayer.cpp + lltexlayerparams.cpp lltexturecache.cpp lltexturectrl.cpp lltexturefetch.cpp @@ -550,7 +563,7 @@ set(viewer_SOURCE_FILES rlvinventory.cpp rlvextensions.cpp rlvfloaterbehaviour.cpp - rlvviewer2.cpp + rlvui.cpp shcommandhandler.cpp shfloatermediaticker.cpp ) @@ -571,7 +584,6 @@ set(viewer_HEADER_FILES aoremotectrl.h floaterao.h floatervoicelicense.h - cofmgr.h lldaycyclemanager.h llenvmanager.h llwlhandlers.h @@ -593,6 +605,7 @@ set(viewer_HEADER_FILES hippolimits.h hipporestrequest.h hippopanelgrids.h + importtracker.h jcfloaterareasearch.h lggdicdownload.h lgghunspell_wrapper.h @@ -607,8 +620,10 @@ set(viewer_HEADER_FILES llagentpilot.h llagentui.h llagentwearables.h + llagentwearablesfetch.h llanimstatelabels.h llappearance.h + llappearancemgr.h llappviewer.h llassetconverter.h llassetuploadresponders.h @@ -630,7 +645,6 @@ set(viewer_HEADER_FILES llcolorswatch.h llcommandhandler.h llcommandlineparser.h - llcompass.h llcompilequeue.h llconfirmationmanager.h llconsole.h @@ -653,6 +667,7 @@ set(viewer_HEADER_FILES lldrawpoolwater.h lldrawpoolwlsky.h lldriverparam.h + lldroptarget.h lldynamictexture.h llemote.h lleventinfo.h @@ -794,14 +809,17 @@ set(viewer_HEADER_FILES lljoystickbutton.h lllandmarklist.h lllightconstants.h + lllocaltextureobject.h lllocalinventory.h lllogchat.h llloginhandler.h llsavedlogins.h + llmainlooprepeater.h llmanip.h llmaniprotate.h llmanipscale.h llmaniptranslate.h + llmarketplacenotifications.h llmediaremotectrl.h llmemoryview.h llmenucommands.h @@ -815,12 +833,14 @@ set(viewer_HEADER_FILES llnamelistctrl.h llnetmap.h llnotify.h + lloutfitobserver.h lloverlaybar.h llpanelaudioprefs.h llpanelaudiovolume.h llpanelavatar.h llpanelclassified.h llpanelcontents.h + llpaneleditwearable.h llpaneldebug.h llpaneldirbrowser.h llpaneldirclassified.h @@ -843,7 +863,7 @@ set(viewer_HEADER_FILES llpanelgrouproles.h llpanelgroupvoting.h llpanelinput.h - llpanelinventory.h + llpanelobjectinventory.h llpanelland.h llpanellandaudio.h llpanellandmedia.h @@ -886,6 +906,8 @@ set(viewer_HEADER_FILES llremoteparcelrequest.h llresourcedata.h llsavedsettingsglue.h + llscrollingpanelparam.h + llscrollingpanelparambase.h llselectmgr.h llsky.h llspatialpartition.h @@ -900,7 +922,9 @@ set(viewer_HEADER_FILES llsurface.h llsurfacepatch.h lltable.h + lltexglobalcolor.h lltexlayer.h + lltexlayerparams.h lltexturecache.h lltexturectrl.h lltexturefetch.h @@ -1048,8 +1072,8 @@ set(viewer_HEADER_FILES rlvinventory.h rlvextensions.h rlvfloaterbehaviour.h - rlvviewer2.h - shcommandhandler.h + rlvui.h + shcommandhandler.h shfloatermediaticker.h ) @@ -1340,39 +1364,40 @@ if (OPENAL) endif (OPENAL) if (FMOD OR FMODEX) - if(FMODEX) - set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX") - endif(FMODEX) - if(FMOD) + if (FMODEX) + set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX") + endif (FMODEX) + if (FMOD) set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMOD") - endif(FMOD) + endif (FMOD) - if (NOT WINDOWS) + if (DARWIN) set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp) add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES}) - if(FMOD AND FMODEX) - set(fmodwrapper_needed_LIBRARIES "${FMODEX_LIBRARY} ${FMOD_LIBRARY}") - else(FMOD AND FMODEX) - if(FMODEX) - set(fmodwrapper_needed_LIBRARIES ${FMODEX_LIBRARY}) - endif(FMODEX) - if(FMOD) - set(fmodwrapper_needed_LIBRARIES "${FMOD_LIBRARY}") - endif(FMOD) - endif(FMOD AND FMODEX) - if (DARWIN) - list(APPEND fmodwrapper_needed_LIBRARIES ${CARBON_LIBRARY}) - set_target_properties( - fmodwrapper - PROPERTIES - BUILD_WITH_INSTALL_RPATH 1 - INSTALL_NAME_DIR "@executable_path/../Resources" - LINK_FLAGS "-unexported_symbols_list \"${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp\"" - ) - endif (DARWIN) + if (FMODEX) + set(fmodwrapper_needed_LIBRARIES ${FMODEX_LIBRARY} ${CARBON_LIBRARY}) + endif (FMODEX) + if (FMOD) + set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY}) + endif (FMOD) + set_target_properties( + fmodwrapper + PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path/../Resources" + LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp" + ) set(FMODWRAPPER_LIBRARY fmodwrapper) target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES}) - endif (NOT WINDOWS) + else (DARWIN) + # fmodwrapper unnecessary on linux or windows, for fmod and fmodex + if (FMODEX) + set(FMODWRAPPER_LIBRARY ${FMODEX_LIBRARY}) + endif (FMODEX) + if (FMOD) + set(FMODWRAPPER_LIBRARY ${FMOD_LIBRARY}) + endif (FMOD) + endif (DARWIN) endif (FMOD OR FMODEX) set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") @@ -1522,6 +1547,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLVFS_LIBRARIES} ${LLWINDOW_LIBRARIES} ${LLXML_LIBRARIES} + ${LLXUIXML_LIBRARIES} ${LSCRIPT_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} diff --git a/indra/newview/app_settings/CA.pem b/indra/newview/app_settings/CA.pem index 63bb036c9..8c1b9a1f3 100644 --- a/indra/newview/app_settings/CA.pem +++ b/indra/newview/app_settings/CA.pem @@ -1,362 +1,322 @@ -----BEGIN CERTIFICATE----- -MIIEuDCCA6CgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBtDELMAkGA1UEBhMCQlIx -EzARBgNVBAoTCklDUC1CcmFzaWwxPTA7BgNVBAsTNEluc3RpdHV0byBOYWNpb25h -bCBkZSBUZWNub2xvZ2lhIGRhIEluZm9ybWFjYW8gLSBJVEkxETAPBgNVBAcTCEJy -YXNpbGlhMQswCQYDVQQIEwJERjExMC8GA1UEAxMoQXV0b3JpZGFkZSBDZXJ0aWZp -Y2Fkb3JhIFJhaXogQnJhc2lsZWlyYTAeFw0wMTExMzAxMjU4MDBaFw0xMTExMzAy -MzU5MDBaMIG0MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE9MDsG -A1UECxM0SW5zdGl0dXRvIE5hY2lvbmFsIGRlIFRlY25vbG9naWEgZGEgSW5mb3Jt -YWNhbyAtIElUSTERMA8GA1UEBxMIQnJhc2lsaWExCzAJBgNVBAgTAkRGMTEwLwYD -VQQDEyhBdXRvcmlkYWRlIENlcnRpZmljYWRvcmEgUmFpeiBCcmFzaWxlaXJhMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwPMudwX/hvm+Uh2b/lQAcHVA -isamaLkWdkwP9/S/tOKIgRrL6Oy+ZIGlOUdd6uYtk9Ma/3pUpgcfNAj0vYm5gsyj -Qo9emsc+x6m4VWwk9iqMZSCK5EQkAq/Ut4n7KuLE1+gdftwdIgxfUsPt4CyNrY50 -QV57KM2UT8x5rrmzEjr7TICGpSUAl2gVqe6xaii+bmYR1QrmWaBSAG59LrkrjrYt -bRhFboUDe1DK+6T8s5L6k8c8okpbHpa9veMztDVC9sPJ60MWXh6anVKo1UcLcbUR -yEeNvZneVRKAAU6ouwdjDvwlsaKydFKwed0ToQ47bmUKgcm+wV3eTRk36UOnTwID -AQABo4HSMIHPME4GA1UdIARHMEUwQwYFYEwBAQAwOjA4BggrBgEFBQcCARYsaHR0 -cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0RQQ2FjcmFpei5wZGYwPQYDVR0f -BDYwNDAyoDCgLoYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0xDUmFj -cmFpei5jcmwwHQYDVR0OBBYEFIr68VeEERM1kEL6V0lUaQ2kxPA3MA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAZA5c1 -U/hgIh6OcgLAfiJgFWpvmDZWqlV30/bHFpj8iBobJSm5uDpt7TirYh1Uxe3fQaGl -YjJe+9zd+izPRbBqXPVQA34EXcwk4qpWuf1hHriWfdrx8AcqSqr6CuQFwSr75Fos -SzlwDADa70mT7wZjAmQhnZx2xJ6wfWlT9VQfS//JYeIc7Fue2JNLd00UOSMMaiK/ -t79enKNHEA2fupH3vEigf5Eh4bVAN5VohrTm6MY53x7XQZZr1ME7a55lFEnSeT0u -mlOAjR2mAbvSM5X5oSZNrmetdzyTj2flCM8CC7MLab0kkdngRIlUBGHF1/S5nmPb -K+9A46sd33oqK8n8 +MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT +MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0 +aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw +WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE +AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m +OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu +T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c +JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR +Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz +PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm +aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM +TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g +LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO +BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv +dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB +AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL +NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W +b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIGCDCCA/CgAwIBAgIBATANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 -IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB -IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA -Y2FjZXJ0Lm9yZzAeFw0wNTEwMTQwNzM2NTVaFw0zMzAzMjgwNzM2NTVaMFQxFDAS -BgNVBAoTC0NBY2VydCBJbmMuMR4wHAYDVQQLExVodHRwOi8vd3d3LkNBY2VydC5v -cmcxHDAaBgNVBAMTE0NBY2VydCBDbGFzcyAzIFJvb3QwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCrSTURSHzSJn5TlM9Dqd0o10Iqi/OHeBlYfA+e2ol9 -4fvrcpANdKGWZKufoCSZc9riVXbHF3v1BKxGuMO+f2SNEGwk82GcwPKQ+lHm9WkB -Y8MPVuJKQs/iRIwlKKjFeQl9RrmK8+nzNCkIReQcn8uUBByBqBSzmGXEQ+xOgo0J -0b2qW42S0OzekMV/CsLj6+YxWl50PpczWejDAz1gM7/30W9HxM3uYoNSbi4ImqTZ -FRiRpoWSR7CuSOtttyHshRpocjWr//AQXcD0lKdq1TuSfkyQBX6TwSyLpI5idBVx -bgtxA+qvFTia1NIFcm+M+SvrWnIl+TlG43IbPgTDZCciECqKT1inA62+tC4T7V2q -SNfVfdQqe1z6RgRQ5MwOQluM7dvyz/yWk+DbETZUYjQ4jwxgmzuXVjit89Jbi6Bb -6k6WuHzX1aCGcEDTkSm3ojyt9Yy7zxqSiuQ0e8DYbF/pCsLDpyCaWt8sXVJcukfV -m+8kKHA4IC/VfynAskEDaJLM4JzMl0tF7zoQCqtwOpiVcK01seqFK6QcgCExqa5g -eoAmSAC4AcCTY1UikTxW56/bOiXzjzFU6iaLgVn5odFTEcV7nQP2dBHgbbEsPyyG -kZlxmqZ3izRg0RS0LKydr4wQ05/EavhvE/xzWfdmQnQeiuP43NJvmJzLR5iVQAX7 -6QIDAQABo4G/MIG8MA8GA1UdEwEB/wQFMAMBAf8wXQYIKwYBBQUHAQEEUTBPMCMG -CCsGAQUFBzABhhdodHRwOi8vb2NzcC5DQWNlcnQub3JnLzAoBggrBgEFBQcwAoYc -aHR0cDovL3d3dy5DQWNlcnQub3JnL2NhLmNydDBKBgNVHSAEQzBBMD8GCCsGAQQB -gZBKMDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuQ0FjZXJ0Lm9yZy9pbmRleC5w -aHA/aWQ9MTAwDQYJKoZIhvcNAQEEBQADggIBAH8IiKHaGlBJ2on7oQhy84r3HsQ6 -tHlbIDCxRd7CXdNlafHCXVRUPIVfuXtCkcKZ/RtRm6tGpaEQU55tiKxzbiwzpvD0 -nuB1wT6IRanhZkP+VlrRekF490DaSjrxC1uluxYG5sLnk7mFTZdPsR44Q4Dvmw2M -77inYACHV30eRBzLI++bPJmdr7UpHEV5FpZNJ23xHGzDwlVks7wU4vOkHx4y/CcV -Bc/dLq4+gmF78CEQGPZE6lM5+dzQmiDgxrvgu1pPxJnIB721vaLbLmINQjRBvP+L -ivVRIqqIMADisNS8vmW61QNXeZvo3MhN+FDtkaVSKKKs+zZYPumUK5FQhxvWXtaM -zPcPEAxSTtAWYeXlCmy/F8dyRlecmPVsYGN6b165Ti/Iubm7aoW8mA3t+T6XhDSU -rgCvoeXnkm5OvfPi2RSLXNLrAWygF6UtEOucekq9ve7O/e0iQKtwOIj1CodqwqsF -YMlIBdpTwd5Ed2qz8zw87YC8pjhKKSRf/lk7myV6VmMAZLldpGJ9VzZPrYPvH5JT -oI53V93lYRE9IwCQTDz6o2CTBKOvNfYOao9PSmCnhQVsRqGP9Md246FZV/dxssRu -FFxtbUFm3xuTsdQAw+7Lzzw9IYCpX2Nl/N3gX6T0K/CFcUHUZyX7GrGXrtaZghNB -0m6lG5kngOcLqagA +MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg +Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 +MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi +U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh +cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk +pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf +OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C +Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT +Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi +HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM +Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w ++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ +Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 +Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B +26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID +AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul +F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC +ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w +ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk +aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 +YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg +c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 +d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG +CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF +wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS +Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst +0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc +pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl +CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF +P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK +1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm +KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE +JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ +8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm +fyWl8kgAwKQB2j8= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 -IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB -IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA -Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO -BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi -MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ -ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ -8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6 -zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y -fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7 -w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc -G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k -epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q -laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ -QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU -fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826 -YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w -ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY -gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe -MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0 -IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy -dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw -czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0 -dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl -aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC -AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg -b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB -ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc -nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg -18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c -gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl -Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY -sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T -SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF -CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum -GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk -zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW -omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD +MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy +MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA +vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G +CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA +WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo +oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ +h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18 +f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN +B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy +vUxFnmG6v4SBkgPR0ml8xQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIESzCCAzOgAwIBAgIJAJigUTEEXRQpMA0GCSqGSIb3DQEBBQUAMHYxCzAJBgNV -BAYTAkRFMQ8wDQYDVQQIEwZIZXNzZW4xDjAMBgNVBAcTBUZ1bGRhMRAwDgYDVQQK -EwdEZWJjb25mMRMwEQYDVQQDEwpEZWJjb25mIENBMR8wHQYJKoZIhvcNAQkBFhBq -b2VyZ0BkZWJpYW4ub3JnMB4XDTA1MTEwNTE3NTUxNFoXDTE1MTEwMzE3NTUxNFow -djELMAkGA1UEBhMCREUxDzANBgNVBAgTBkhlc3NlbjEOMAwGA1UEBxMFRnVsZGEx -EDAOBgNVBAoTB0RlYmNvbmYxEzARBgNVBAMTCkRlYmNvbmYgQ0ExHzAdBgkqhkiG -9w0BCQEWEGpvZXJnQGRlYmlhbi5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQCvbOo0SrIwI5IMlsshH8WF3dHB9r9JlSKhMPaybawa1EyvZspMQ3wa -F5qxNf3Sj+NElEmjseEqvCZiIIzqwerHu0Qw62cDYCdCd2+Wb5m0bPYB5CGHiyU1 -eNP0je42O0YeXG2BvUujN8AviocVo39X2YwNQ0ryy4OaqYgm2pRlbtT2ESbF+SfV -Y2iqQj/f8ymF+lHo/pz8tbAqxWcqaSiHFAVQJrdqtFhtoodoNiE3q76zJoUkZTXB -k60Yc3MJSnatZCpnsSBr/D7zpntl0THrUjjtdRWCjQVhqfhM1yZJV+ApbLdheFh0 -ZWlSxdnp25p0q0XYw/7G92ELyFDfBUUNAgMBAAGjgdswgdgwHQYDVR0OBBYEFMuV -dFNb4mCWUFbcP5LOtxFLrEVTMIGoBgNVHSMEgaAwgZ2AFMuVdFNb4mCWUFbcP5LO -txFLrEVToXqkeDB2MQswCQYDVQQGEwJERTEPMA0GA1UECBMGSGVzc2VuMQ4wDAYD -VQQHEwVGdWxkYTEQMA4GA1UEChMHRGViY29uZjETMBEGA1UEAxMKRGViY29uZiBD -QTEfMB0GCSqGSIb3DQEJARYQam9lcmdAZGViaWFuLm9yZ4IJAJigUTEEXRQpMAwG -A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGZXxHg4mnkvilRIM1EQfGdY -S5b/WcyF2MYSTeTvK4aIB6VHwpZoZCnDGj2m2D3CkHT0upAD9o0zM1tdsfncLzV+ -mDT/jNmBtYo4QXx5vEPwvEIcgrWjwk7SyaEUhZjtolTkHB7ACl0oD0r71St4iEPR -qTUCEXk2E47bg1Fz58wNt/yo2+4iqiRjg1XCH4evkQuhpW+dTZnDyFNqwSYZapOE -TBA+9zBb6xD1KM2DdY7r4GiyYItN0BKLfuWbh9LXGbl1C+f4P11g+m2MPiavIeCe -1iazG5pcS3KoTLACsYlEX24TINtg4kcuS81XdllcnsV3Kdts0nIqPj6uhTTZD0k= +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy +c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 +IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV +VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 +cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT +QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh +F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v +c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w +mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd +VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX +teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ +f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe +Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ +nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB +/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY +MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG +9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX +IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn +ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z +uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN +Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja +QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW +koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 +ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt +DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm +bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs -IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 -MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux -FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h -bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v -dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt -H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 -uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX -mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX -a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN -E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 -WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD -VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 -Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU -cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx -IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN -AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH -YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 -6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC -Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX -c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a -mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt +YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu +Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT +AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa +MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp +b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG +cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh +d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY +DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E +rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq +uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN +BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP +MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa +/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei +gQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw -MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD -VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA -A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul -CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n -tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl -dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch -PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC -+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O -BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl -MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk -ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB -IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X -7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz -43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY -eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl -pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA -WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= +MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg +b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa +MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB +ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw +IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B +AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb +unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d +BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq +7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 +0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX +roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG +A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j +aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p +26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA +BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud +EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN +BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB +AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd +p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi +1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc +XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 +eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu +tGWaIZDgqtCYvDi1czyL+Nw= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx -MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB -ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV -BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV -6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX -GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP -dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH -1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF -62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW -BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw -AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL -MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU -cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv -b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 -IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ -iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao -GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh -4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm -XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= +MIID/TCCA2agAwIBAgIEP4/gkTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJQ +TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu +dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQgLSBD +QSBLbGFzYSAxMB4XDTAzMTAxNzEyMjkwMloXDTExMDkyMzExMTgxN1owdjELMAkG +A1UEBhMCUEwxHzAdBgNVBAoTFlRQIEludGVybmV0IFNwLiB6IG8uby4xJDAiBgNV +BAsTG0NlbnRydW0gQ2VydHlmaWthY2ppIFNpZ25ldDEgMB4GA1UEAxMXQ0MgU2ln +bmV0IC0gVFNBIEtsYXNhIDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOJY +rISEtSsduHajROh5/n7NGrkpYTT9NEaPe9+ucuQ37KxIbfJwXJjgUc1dw4wCkcQ1 +2FJarD1X6mSQ4cfN/60vLfKI5ZD4nhJTMKlAj1pX9ScQ/MuyvKStCbn5WTkjPhjR +AM0tdwXSnzuTEunfw0Oup559y3Iqxg1cExflB6cfAgMBAAGjggGXMIIBkzBBBgNV +HR8EOjA4MDagNKAyhjBodHRwOi8vd3d3LnNpZ25ldC5wbC9yZXBvenl0b3JpdW0v +Y3JsL2tsYXNhMS5jcmwwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsG +AQUFBwMIMIHaBgNVHSAEgdIwgc8wgcwGDSsGAQQBvj8CZAoRAgEwgbowbwYIKwYB +BQUHAgIwYxphQ2VydHlmaWthdCB3eXN0YXdpb255IHpnb2RuaWUgeiBkb2t1bWVu +dGVtICJQb2xpdHlrYSBDZXJ0eWZpa2FjamkgQ0MgU2lnbmV0IC0gWm5ha293YW5p +ZSBjemFzZW0iLjBHBggrBgEFBQcCARY7aHR0cDovL3d3dy5zaWduZXQucGwvcmVw +b3p5dG9yaXVtL2Rva3VtZW50eS9wY190c2ExXzJfMS5wZGYwHwYDVR0jBBgwFoAU +w4Me1Vl3VPtN+1dH+cQjXNHnieMwHQYDVR0OBBYEFJdDwEqtcavOYd9u9tej53vW +XwNBMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADgYEAnpiQkqLCJQYXUrqMHUEz ++z3rOqS0XzSFnVVLhkVssvXc8S3FkJIiQTUrkScjI4CToCzujj3EyfNxH6yiLlMb +skF8I31JxIeBvueqV+s+o76CZm3ycu9hb0I4lswuxoT+q5ZzPR8Irrb51rZXlolR ++7KtwMg4sFDJZ8RNgOf7tbA= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 -MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK -EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh -BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq -xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G -87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i -2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U -WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 -0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G -A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr -pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL -ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm -aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv -hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm -hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X -dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 -P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y -iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no -xqE= +MIIDlDCCAnygAwIBAgIQWAsFbFMk27JQVxhf+eWmUDANBgkqhkiG9w0BAQUFADAn +MQswCQYDVQQGEwJCRTEYMBYGA1UEAxMPQmVsZ2l1bSBSb290IENBMB4XDTAzMDEy +NjIzMDAwMFoXDTE0MDEyNjIzMDAwMFowJzELMAkGA1UEBhMCQkUxGDAWBgNVBAMT +D0JlbGdpdW0gUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMihcekcRkJ5eHFvna6pqKsot03HIOswkVp19eLSz8hMFJhCWK3HEcVAQGpa+XQS +J4fpnOVxTiIs0RIYqjBeoiG52bv/9nTrMQHnO35YD5EWTXaJqAFPrSJmcPpLHZXB +MFjqvNll2Jq0iOtJRlLf0lMVdssUXRlJsW9q09P9vMIt7EU/CT9YvvzU7wCMgTVy +v/cY6pZifSsofxVsY9LKyn0FrMhtB20yvmi4BUCuVJhWPmbxMOjvxKuTXgfeMo8S +dKpbNCNUwOpszv42kqgJF+qhLc9s44Qd3ocuMws8dOIhUDiVLlzg5cYx+dtA+mqh +pIqTm6chBocdJ9PEoclMsG8CAwEAAaOBuzCBuDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zBCBgNVHSAEOzA5MDcGBWA4AQEBMC4wLAYIKwYBBQUHAgEW +IGh0dHA6Ly9yZXBvc2l0b3J5LmVpZC5iZWxnaXVtLmJlMB0GA1UdDgQWBBQQ8AxW +m2HqVzq2NZdtn925FI7b5jARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAU +EPAMVpth6lc6tjWXbZ/duRSO2+YwDQYJKoZIhvcNAQEFBQADggEBAMhtIlGKYfgP +lm7VILKB+MbcoxYA2s1q52sq+llIp0xJN9dzoWoBZV4yveeX09AuPHPTjHuD79ZC +wT+oqV0PN7p20kC9zC0/00RBSZz9Wyn0AiMiW3Ebv1jZKE4tRfTa57VjRUQRDSp/ +M382SbTObqkCMa5c/ciJv0J71/Fg8teH9lcuen5qE4Ad3OPQYx49cTGxYNSeCMqr +8JTHSHVUgfMbrXec6LKP24OsjzRr6L/D2fVDw2RV6xq9NoY2uiGMlxoh1OotO6y6 +7Kcdq765Sps1LxxcHVGnH1TtEpf/8m6HfUbJdNbv6z195lluBpQE5KJVhzgoaiJe +4r50ErAEQyo= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP -bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2 -MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft -ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk -hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym -1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW -OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb -2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko -O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU -AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB -BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF -Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb -LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir -oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C -MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds -sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 +MIIH8jCCB1ugAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl +SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl +SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 +DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIzMTExMTEwM1oXDTI1MTIyOTEx +MTEwM1owggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD +VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n +IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g +IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA55+R7+voFuF0vIkTodduR8ZfPxKU5u/h +M+GrgqufAwHmdG+KF5fPVy8Mdi7mbqfK2veLFBVADbNq2e2+s2q8Ai0chS3vl//P +l9rrR10eU79dVN4ndGMZfpXUMZblz0/Kq3Uvk5AsWUwfv1YokIhi4RMeBtOCVv3j +LSV1rDsiap8CAwEAAaOCBFIwggROMB0GA1UdDgQWBBRtW6MBjmE3nQR4tq+blh0C +QeXbeTCCAUQGA1UdIwSCATswggE3gBRtW6MBjmE3nQR4tq+blh0CQeXbeaGCARqk +ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE +BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT +ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC +LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD +VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr +BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB +FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC +AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB +D2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0UxIENBIENlcnRp +ZmljYXRlIGlzc3VlZCBieSBodHRwczovL3d3dy5pcHMuZXMvMCoGCWCGSAGG+EIB +AgQdFhtodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi8wOwYJYIZIAYb4QgEEBC4W +LGh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEuY3JsMEAG +CWCGSAGG+EIBAwQzFjFodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9yZXZvY2F0 +aW9uQ0xBU0UxLmh0bWw/MD0GCWCGSAGG+EIBBwQwFi5odHRwczovL3d3dy5pcHMu +ZXMvaXBzMjAwMi9yZW5ld2FsQ0xBU0UxLmh0bWw/MDsGCWCGSAGG+EIBCAQuFixo +dHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTEuaHRtbDB1BgNV +HR8EbjBsMDKgMKAuhixodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy +Q0xBU0UxLmNybDA2oDSgMoYwaHR0cHM6Ly93d3diYWNrLmlwcy5lcy9pcHMyMDAy +L2lwczIwMDJDTEFTRTEuY3JsMC8GCCsGAQUFBwEBBCMwITAfBggrBgEFBQcwAYYT +aHR0cDovL29jc3AuaXBzLmVzLzANBgkqhkiG9w0BAQUFAAOBgQBacEdMbCU0z2bO +X+iyJafrUbjPE+5KzJz2jB1YXC2d7kMy2Hhbp8gVyfUFQpd+F2IgBBj9z3IRNkDN +foHhdse5j2cUUH+fno9jj8EPE2GPhXVmCjIP6KuPp8yzz89gC+ry+bkfSFzjHUQt +K15I/jRAHfyJywwUrwtmklZIX0E5Og== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP -bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2 -MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft -ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC -206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci -KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2 -JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9 -BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e -Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B -PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67 -Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq -Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ -o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3 -+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj -YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj -FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE -AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn -xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2 -LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc -obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8 -CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe -IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA -DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F -AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX -Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb -AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl -Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw -RY8mkaKO/qk= +MIIDWjCCAkKgAwIBAgIEO8rJUjANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJE +SzEMMAoGA1UEChMDS01EMQ8wDQYDVQQLEwZLTUQtQ0ExFjAUBgNVBAMTDUtNRC1D +QSBTZXJ2ZXIxIDAeBgoJkiaJk/IsZAEDFBBpbmZvY2FAa21kLWNhLmRrMB4XDTk4 +MTAxNjE5MTkyMVoXDTE4MTAxMjE5MTkyMVowZjELMAkGA1UEBhMCREsxDDAKBgNV +BAoTA0tNRDEPMA0GA1UECxMGS01ELUNBMRYwFAYDVQQDEw1LTUQtQ0EgU2VydmVy +MSAwHgYKCZImiZPyLGQBAxQQaW5mb2NhQGttZC1jYS5kazCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAJsLpbSgFxQ7IhFgf5f+RfBxnbCkx5C7yTjfCZvp +/BP2LBD3OKjgLRwvASoCU3I5NMhccho6uhZVf1HC+Ac5HmXUUd+v92a7gDnohPPy +Rgv8c6f/+R2fFen37SBemYFDtZveamVXZ2To7xAxNiMKgPTPs/Rl7F6LDsYgv1bD +36FrjahNoSTmTbYRoK21eIOVwrZeNSzo9w3W8fj0n+V2IB1jsOh+AvjXkjbvAVky +0/57GMlyBNKP7JIGP7LXqwWfrBXuAph1DUMz467KlHZOMkPwCjTZOab7CcLQXCCY +12s5c5QAkwpf35hQRuOaNo6d/XFM6J9mofiWlGTT3Px1EX0CAwEAAaMQMA4wDAYD +VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAPlA6VZ2C2cJbsI0SBIe9v+M9 +GxI45QI7P0D7QGyrqM7oNqGq7hJdN6NFb0LyPcF3/pVzmtYVJzaGKF6spaxOEveB +9ki1xRoXUKpaCxSweBpTzEktWa43OytRy0sbryEmHJCQkz8MPufWssf2yXHzgFFo +XMQpcMyT7JwxPlfYVvab9Kp+nW7fIyDOG0wdmBerZ+GEQJxJEkri1HskjigxhGze +ziocJatBuOWgqw5KRylgGIQjUGRTCbODVta+Kmqb9d+cB7FStbYtt2HebOXzBIY3 +XUM5KtGC++We7DqgU5Firek7brw8i2XsHPLKJTceb6Xo6DsSxLfBAWV6+8DCkQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx -HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh -IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyOTA2MDAwMFoXDTM3MTEyMDE1 -MDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg -SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M -IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnej8Mlo2k06AX3dLm/WpcZuS+U -0pPlLYnKhHw/EEMbjIt8hFj4JHxIzyr9wBXZGH6EGhfT257XyuTZ16pYUYfw8ItI -TuLCxFlpMGK2MKKMCxGZYTVtfu/FsRkGIBKOQuHfD5YQUqjPnF+VFNivO3ULMSAf -RC+iYkGzuxgh28pxPIzstrkNn+9R7017EvILDOGsQI93f7DKeHEMXRZxcKLXwjqF -zQ6axOAAsNUl6twr5JQtOJyJQVdkKGUZHLZEtMgxa44Be3ZZJX8VHIQIfHNlIAqh -BC4aMqiaILGcLCFZ5/vP7nAtCMpjPiybkxlqpMKX/7eGV4iFbJ4VFitNLLMCAwEA -AaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoTYwFsuGkABFgFOxj8jY -PXy+XxIwHwYDVR0jBBgwFoAUoTYwFsuGkABFgFOxj8jYPXy+XxIwDgYDVR0PAQH/ -BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQCKIBilvrMvtKaEAEAwKfq0FHNMeUWn -9nDg6H5kHgqVfGphwu9OH77/yZkfB2FK4V1Mza3u0FIy2VkyvNp5ctZ7CegCgTXT -Ct8RHcl5oIBN/lrXVtbtDyqvpxh1MwzqwWEFT2qaifKNuZ8u77BfWgDrvq2g+EQF -Z7zLBO+eZMXpyD8Fv8YvBxzDNnGGyjhmSs3WuEvGbKeXO/oTLW4jYYehY0KswsuX -n2Fozy1MBJ3XJU8KDk2QixhWqJNIV9xvrr2eZ1d3iVCzvhGbRWeDhhmH05i9CBoW -H1iCC+GWaQVLjuyDUTEH1dSf/1l7qG6Fz9NLqUmwX7A5KGgOc90lmt4S +MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOc +UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMQswCQYDVQQGDAJUUjEPMA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykg +MjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 +dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMxMDI3MTdaFw0xNTAz +MjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2Vy +dGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYD +VQQHDAZBTktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kg +xLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEu +xZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7 +XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GXyGl8hMW0kWxsE2qkVa2k +heiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8iSi9BB35J +YbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5C +urKZ8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1 +JuTm5Rh8i27fbMx4W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51 +b0dewQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV +9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46sWrv7/hg0Uw2ZkUd82YCdAR7 +kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxEq8Sn5RTOPEFh +fEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy +B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdA +aLX/7KfS0zgYnNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKS +RGQDJereW26fyfJOrN3H -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIF5jCCA86gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx -HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh -IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyOTA2MDAwMFoXDTM3MDkyODIz -NDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg -SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M -IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALQ3WggWmRToVbEbJGv8x4vmh6mJ -7ouZzU9AhqS2TcnZsdw8TQ2FTBVsRotSeJ/4I/1n9SQ6aF3Q92RhQVSji6UI0ilb -m2BPJoPRYxJWSXakFsKlnUWsi4SVqBax7J/qJBrvuVdcmiQhLE0OcR+mrF1FdAOY -xFSMFkpBd4aVdQxHAWZg/BXxD+r1FHjHDtdugRxev17nOirYlxcwfACtCJ0zr7iZ -YYCLqJV+FNwSbKTQ2O9ASQI2+W6p1h2WVgSysy0WVoaP2SBXgM1nEG2wTPDaRrbq -JS5Gr42whTg0ixQmgiusrpkLjhTXUr2eacOGAgvqdnUxCc4zGSGFQ+aJLZ8lN2fx -I2rSAG2X+Z/nKcrdH9cG6rjJuQkhn8g/BsXS6RJGAE57COtCPStIbp1n3UsC5ETz -kxmlJ85per5n0/xQpCyrw2u544BMzwVhSyvcG7mm0tCq9Stz+86QNZ8MUhy/XCFh -EVsVS6kkUfykXPcXnbDS+gfpj1bkGoxoigTTfFrjnqKhynFbotSg5ymFXQNoKk/S -Btc9+cMDLz9l+WceR0DTYw/j1Y75hauXTLPXJuuWCpTehTacyH+BCQJJKg71ZDIM -gtG6aoIbs0t0EfOMd9afv9w3pKdVBC/UMejTRrkDfNoSTllkt1ExMVCgyhwn2RAu -rda9EGYrw7AiShJbAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE -FE9pbQN+nZ8HGEO8txBO1b+pxCAoMB8GA1UdIwQYMBaAFE9pbQN+nZ8HGEO8txBO -1b+pxCAoMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAO/Ouyugu -h4X7ZVnnrREUpVe8WJ8kEle7+z802u6teio0cnAxa8cZmIDJgt43d15Ui47y6mdP -yXSEkVYJ1eV6moG2gcKtNuTxVBFT8zRFASbI5Rq8NEQh3q0l/HYWdyGQgJhXnU7q -7C+qPBR7V8F+GBRn7iTGvboVsNIYvbdVgaxTwOjdaRITQrcCtQVBynlQboIOcXKT -RuidDV29rs4prWPVVRaAMCf/drr3uNZK49m1+VLQTkCpx+XCMseqdiThawVQ68W/ -ClTluUI8JPu3B5wwn3la5uBAUhX0/Kr0VvlEl4ftDmVyXr4m+02kLQgH3thcoNyB -M5kYJRF3p+v9WAksmWsbivNSPxpNSGDxoPYzAlOL7SUJuA0t7Zdz7NeWH45gDtoQ -my8YJPamTQr5O8t1wswvziRpyQoijlmn94IM19drNZxDAGrElWe6nEXLuA4399xO -AU++CrYD062KRffaJ00psUjf5BHklka9bAI+1lHIlRcBFanyqqryvy9lG2/QuRqT -9Y41xICHPpQvZuTpqP9BnHAqTyo5GJUefvthATxRCC4oGKQWDzH9OmwjkyB24f0H -hdFbP9IcczLd+rn4jM8Ch3qaluTtT4mNU0OrDhPAARW0eTjb/G49nlG2uBOLZ8/5 -fNkiHfZdxRwBL5joeiQYvITX+txyW/fBOmg= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT +ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw +MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j +LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ +KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo +RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu +WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw +Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD +AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK +eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM +zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ +WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN +/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFajCCBFKgAwIBAgIEPLU9RjANBgkqhkiG9w0BAQUFADBmMRIwEAYDVQQKEwli @@ -390,184 +350,85 @@ gkHNZTfqjjJ+vWuZXTARyNtIVBw74acT02pIk/c9jH8F6M7ziCpjBLjqflh8AXtb CReJf8Py05yc493EG931t3GzUwWJBtDLSoDByFOQtTwxiBdQn8nEDovYqAJjDQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIGUTCCBTmgAwIBAgIEPLVPQDANBgkqhkiG9w0BAQUFADBmMRIwEAYDVQQKEwli -ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEzMDEGA1UEAxMq -YmVUUlVTVGVkIFJvb3QgQ0EgLSBFbnRydXN0IEltcGxlbWVudGF0aW9uMB4XDTAy -MDQxMTA4MjQyN1oXDTIyMDQxMTA4NTQyN1owZjESMBAGA1UEChMJYmVUUlVTVGVk -MRswGQYDVQQLExJiZVRSVVNUZWQgUm9vdCBDQXMxMzAxBgNVBAMTKmJlVFJVU1Rl -ZCBSb290IENBIC0gRW50cnVzdCBJbXBsZW1lbnRhdGlvbjCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBALr0RAOqEmq1Q+xVkrYwfTVXDNvzDSduTPdQqJtO -K2/b9a0cS12zqcH+e0TrW6MFDR/FNCswACnxeECypP869AGIF37m1CbTukzqMvtD -d5eHI8XbQ6P1KqNRXuE70mVpflUVm3rnafdE4Fe1FehmYA8NA/uCjqPoEXtsvsdj -DheT389Lrm5zdeDzqrmkwAkbhepxKYhBMvnwKg5sCfJ0a2ZsUhMfGLzUPvfYbiCe -yv78IZTuEyhL11xeDGbu6bsPwTSxfwh28z0mcMmLJR1iJAzqHHVOwBLkuhMdMCkt -VjMFu5dZfsZJT4nXLySotohAtWSSU1Yk5KKghbNekLQSM80CAwEAAaOCAwUwggMB -MIIBtwYDVR0gBIIBrjCCAaowggGmBg8rBgEEAbE+AAACCSiDkTEwggGRMIIBSQYI -KwYBBQUHAgIwggE7GoIBN1JlbGlhbmNlIG9uIG9yIHVzZSBvZiB0aGlzIENlcnRp -ZmljYXRlIGNyZWF0ZXMgYW4gYWNrbm93bGVkZ21lbnQgYW5kIGFjY2VwdGFuY2Ug -b2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0 -aW9ucyBvZiB1c2UsIHRoZSBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu -dCBhbmQgdGhlIFJlbHlpbmcgUGFydHkgQWdyZWVtZW50LCB3aGljaCBjYW4gYmUg -Zm91bmQgYXQgdGhlIGJlVFJVU1RlZCB3ZWIgc2l0ZSwgaHR0cHM6Ly93d3cuYmV0 -cnVzdGVkLmNvbS9wcm9kdWN0c19zZXJ2aWNlcy9pbmRleC5odG1sMEIGCCsGAQUF -BwIBFjZodHRwczovL3d3dy5iZXRydXN0ZWQuY29tL3Byb2R1Y3RzX3NlcnZpY2Vz -L2luZGV4Lmh0bWwwEQYJYIZIAYb4QgEBBAQDAgAHMIGJBgNVHR8EgYEwfzB9oHug -eaR3MHUxEjAQBgNVBAoTCWJlVFJVU1RlZDEbMBkGA1UECxMSYmVUUlVTVGVkIFJv -b3QgQ0FzMTMwMQYDVQQDEypiZVRSVVNUZWQgUm9vdCBDQSAtIEVudHJ1c3QgSW1w -bGVtZW50YXRpb24xDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMjA0MTEw -ODI0MjdagQ8yMDIyMDQxMTA4NTQyN1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaA -FH1w5a44iwY/qhwaj/nPJDCqhIQWMB0GA1UdDgQWBBR9cOWuOIsGP6ocGo/5zyQw -qoSEFjAMBgNVHRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIE -kDANBgkqhkiG9w0BAQUFAAOCAQEAKrgXzh8QlOu4mre5X+za95IkrNySO8cgjfKZ -5V04ocI07cUTWVwFtStPYZuR+0H8/NU8TZh2BvWBfevdkObRVlTa4y0MnxEylCIB -evZsLHRnBMylj44ss0O1lKLQfelifwa+JwGDnjr9iu6YQ0pr17WXOzq/T220Y/oz -ADQuLW2WyXvKmWO6vvT2MKAtmJbpVkQFqUSjYRDrgqFnXbxdJ3Wqiig2KjiS2d2k -XgClzMx8KSreKJCrt+G2/30lC0DYqjSjLd4H61/OCt3Kfjp9JsFiaDrmLzfzgYYh -xKlkqu9FNtEaZnz46TfW1mG+oq1I59/mdP7TbX3SJdysYlep9w== +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do +lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc +AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIFaDCCBFCgAwIBAgIQO1nHe81bV569N1KsdrSqGjANBgkqhkiG9w0BAQUFADBi -MRIwEAYDVQQKEwliZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENB -czEvMC0GA1UEAxMmYmVUUlVTVGVkIFJvb3QgQ0EgLSBSU0EgSW1wbGVtZW50YXRp -b24wHhcNMDIwNDExMTExODEzWhcNMjIwNDEyMTEwNzI1WjBiMRIwEAYDVQQKEwli -ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEvMC0GA1UEAxMm -YmVUUlVTVGVkIFJvb3QgQ0EgLSBSU0EgSW1wbGVtZW50YXRpb24wggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkujQwCY5X0LkGLG9uJIAiv11DpvpPrILn -HGhwhRujbrWqeNluB0s/6d/16uhUoWGKDi9pdRi3DOUUjXFumLhV/AyV0Jtu4S2I -1DpAa5LxmZZk3tv/ePTulh1HiXzUvrmIdyM6CeYEnm2qXtLIvZpOGd+J6lsOfsPk -tPDgaTuID0GQ+NRxQyTBjyZLO1bp/4xsN+lFrYWMU8NghpBKlsmzVLC7F/AcRdnU -GxlkVgoZ98zh/4avflherHqQH8koOUV7orbHnB/ahdQhhlkwk75TMzf270HPM8er -cmsl9fNTGwxMLvF1S++gh/f+ihXQbNXL+WhTuXAVE8L1LvtDNXUtAgMBAAGjggIY -MIICFDAMBgNVHRMEBTADAQH/MIIBtQYDVR0gBIIBrDCCAagwggGkBg8rBgEEAbE+ -AAADCSiDkTEwggGPMEEGCCsGAQUFBwIBFjVodHRwOi8vd3d3LmJldHJ1c3RlZC5j -b20vcHJvZHVjdHNfc2VydmljZXMvaW5kZXguaHRtbDCCAUgGCCsGAQUFBwICMIIB -OhqCATZSZWxpYW5jZSBvbiBvciB1c2Ugb2YgdGhpcyBDZXJ0aWZpY2F0ZSBjcmVh -dGVzIGFuIGFja25vd2xlZGdtZW50IGFuZCBhY2NlcHRhbmNlIG9mIHRoZSB0aGVu -IGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdXNl -LCB0aGUgQ2VydGlmaWNhdGlvbiBQcmFjdGljZSBTdGF0ZW1lbnQgYW5kIHRoZSBS -ZWx5aW5nIFBhcnR5IEFncmVlbWVudCwgd2hpY2ggY2FuIGJlIGZvdW5kIGF0IHRo -ZSBiZVRSVVNUZWQgd2ViIHNpdGUsIGh0dHA6Ly93d3cuYmV0cnVzdGVkLmNvbS9w -cm9kdWN0c19zZXJ2aWNlcy9pbmRleC5odG1sMAsGA1UdDwQEAwIBBjAfBgNVHSME -GDAWgBSp7BR++dlDzFMrFK3P9/BZiUHNGTAdBgNVHQ4EFgQUqewUfvnZQ8xTKxSt -z/fwWYlBzRkwDQYJKoZIhvcNAQEFBQADggEBANuXsHXqDMTBmMpWBcCorSZIry0g -6IHHtt9DwSwddUvUQo3neqh03GZCWYez9Wlt2ames30cMcH1VOJZJEnl7r05pmuK -mET7m9cqg5c0Lcd9NUwtNLg+DcTsiCevnpL9UGGCqGAHFFPMZRPB9kdEadIxyKbd -LrML3kqNWz2rDcI1UqJWN8wyiyiFQpyRQHpwKzg21eFzGh/l+n5f3NacOzDq28Bb -J1zTcwfBwvNMm2+fG8oeqqg4MwlYsq78B+g23FW6L09A/nq9BqaBwZMifIYRCgZ3 -SK41ty8ymmFei74pnykkiFY5LKjSq5YDWtRIn7lAhAuYaPsBQ9Yb4gmxlxw= +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM -MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD -QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM -MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD -QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E -jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo -ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI -ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu -Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg -AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7 -HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA -uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa -TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg -xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q -CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x -O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs -6GAqm4VKQPNriiTsBhYscw== +MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg +Q2xhc3MgMiBDQSAxMB4XDTA2MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzEL +MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD +VQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7McXA0 +ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLX +l18xoS830r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVB +HfCuuCkslFJgNJQ72uA40Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B +5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/RuFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3 +WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0PAQH/BAQD +AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLP +gcIV1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+ +DKhQ7SLHrQVMdvvt7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKu +BctN518fV4bVIJwo+28TOPX2EZL2fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHs +h7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5wwDX3OaJdZtB7WZ+oRxKaJyOk +LY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj -YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM -GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua -BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe -3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 -YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR -rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm -ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU -oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v -QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t -b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF -AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q -GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz -Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 -G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi -l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 -smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp -ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow -fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV -BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM -cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S -HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 -CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk -3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz -6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV -HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud -EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv -Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw -Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww -DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 -5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj -Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI -gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ -aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl -izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 -aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla -MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO -BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD -VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW -fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt -TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL -fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW -1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 -kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G -A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v -ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo -dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu -Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ -HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 -pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS -jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ -xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn -dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV -UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL -EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ -BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x -ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg -bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ -j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV -Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG -SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx -JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI -RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw -MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5 -fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i -+DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG -SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN -QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+ -gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl +MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL +MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV +BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 +Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1 +OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i +SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc +VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW +Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q +Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2 +1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq +ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1 +Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX +XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy +dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6 +Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz +JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 +Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN +irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8 +TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6 +g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB +95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj +S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV @@ -589,141 +450,75 @@ xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVL B3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlihw6ID -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEgzCCA+ygAwIBAgIEOJ725DANBgkqhkiG9w0BAQQFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9HQ0NBX0NQUyBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAyMDAw -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVu -dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAyMDcxNjE2NDBaFw0yMDAy -MDcxNjQ2NDBaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0dDQ0FfQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDIwMDAgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCTdLS25MVL1qFof2LV7PdRV7Ny -Spj10InJrWPNTTVRaoTUrcloeW+46xHbh65cJFET8VQlhK8pK5/jgOLZy93GRUk0 -iJBeAZfv6lOm3fzB3ksqJeTpNfpVBQbliXrqpBFXO/x8PTbNZzVtpKklWb1m9fkn -5JVn1j+SgF7yNH0rhQIDAQABo4IBnjCCAZowEQYJYIZIAYb4QgEBBAQDAgAHMIHd -BgNVHR8EgdUwgdIwgc+ggcyggcmkgcYwgcMxFDASBgNVBAoTC0VudHJ1c3QubmV0 -MUAwPgYDVQQLFDd3d3cuZW50cnVzdC5uZXQvR0NDQV9DUFMgaW5jb3JwLiBieSBy -ZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0Lm5l -dCBMaW1pdGVkMTMwMQYDVQQDEypFbnRydXN0Lm5ldCBDbGllbnQgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMDAy -MDcxNjE2NDBagQ8yMDIwMDIwNzE2NDY0MFowCwYDVR0PBAQDAgEGMB8GA1UdIwQY -MBaAFISLdP3FjcD/J20gN0V8/i3OutN9MB0GA1UdDgQWBBSEi3T9xY3A/ydtIDdF -fP4tzrrTfTAMBgNVHRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4w -AwIEkDANBgkqhkiG9w0BAQQFAAOBgQBObzWAO9GK9Q6nIMstZVXQkvTnhLUGJoMS -hAusO7JE7r3PQNsgDrpuFOow4DtifH+La3xKp9U1PL6oXOpLu5OOgGarDyn9TS2/ -GpsKkMWr2tGzhtQvJFJcem3G8v7lTRowjJDyutdKPkN+1MhQGof4T4HHdguEOnKd -zmVml64mXg== +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz +dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG +A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U +cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf +qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ +JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ ++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS +s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 +HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 +70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG +V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S +qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S +5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia +C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX +OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE +FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 +KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B +8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ +MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc +0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ +u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF +u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH +YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 +GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO +RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e +KeC2uAloGRwYQw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIElTCCA/6gAwIBAgIEOJsRPDANBgkqhkiG9w0BAQQFADCBujEUMBIGA1UEChML -RW50cnVzdC5uZXQxPzA9BgNVBAsUNnd3dy5lbnRydXN0Lm5ldC9TU0xfQ1BTIGlu -Y29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDIwMDAg -RW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJl -IFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAyMDQxNzIwMDBa -Fw0yMDAyMDQxNzUwMDBaMIG6MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDE/MD0GA1UE -CxQ2d3d3LmVudHJ1c3QubmV0L1NTTF9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p -dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0Lm5ldCBMaW1pdGVk -MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp -b24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHwV9OcfHO -8GCGD9JYf9Mzly0XonUwtZZkJi9ow0SrqHXmAGc0V55lxyKbc+bT3QgON1WqJUaB -bL3+qPZ1V1eMkGxKwz6LS0MKyRFWmponIpnPVZ5h2QLifLZ8OAfc439PmrkDQYC2 -dWcTC5/oVzbIXQA23mYU2m52H083jIITiQIDAQABo4IBpDCCAaAwEQYJYIZIAYb4 -QgEBBAQDAgAHMIHjBgNVHR8EgdswgdgwgdWggdKggc+kgcwwgckxFDASBgNVBAoT -C0VudHJ1c3QubmV0MT8wPQYDVQQLFDZ3d3cuZW50cnVzdC5uZXQvU1NMX0NQUyBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAyMDAw -IEVudHJ1c3QubmV0IExpbWl0ZWQxOjA4BgNVBAMTMUVudHJ1c3QubmV0IFNlY3Vy -ZSBTZXJ2ZXIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEw -KwYDVR0QBCQwIoAPMjAwMDAyMDQxNzIwMDBagQ8yMDIwMDIwNDE3NTAwMFowCwYD -VR0PBAQDAgEGMB8GA1UdIwQYMBaAFMtswGvjuz7L/CKc/vuLkpyw8m4iMB0GA1Ud -DgQWBBTLbMBr47s+y/winP77i5KcsPJuIjAMBgNVHRMEBTADAQH/MB0GCSqGSIb2 -fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQQFAAOBgQBi24GRzsia -d0Iv7L0no1MPUBvqTpLwqa+poLpIYcvvyQbvH9X07t9WLebKahlzqlO+krNQAraF -JnJj2HVQYnUUt7NQGj/KEQALhUVpbbalrlHhStyCP2yMNLJ3a9kC9n8O6mUE8c1U -yrrJzOCE98g+EZfTYAkYvAX/bIkz8OwVDw== +MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6 +MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp +dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX +BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy +MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp +eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg +/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl +wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh +AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2 +PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu +AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR +MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc +HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/ +Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+ +f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO +rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch +6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3 +7CAFYd4= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy -MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq -K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe -sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX -MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT -XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ -HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH -4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA -vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G -CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA -WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo -oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ -h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18 -f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN -B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy -vUxFnmG6v4SBkgPR0ml8xQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50cnVzdC5u -ZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBsaW1pdHMgbGlh -Yi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV -BAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBaMIHJMQswCQYDVQQGEwJVUzEU -MBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9D -bGllbnRfQ0FfSW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjEl -MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMq -RW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0G -CSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo -6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux -5zDeg7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zm -AqTmT173iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSC -ARkwggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50 -cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5m -by9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMp -IDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQg -Q2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCyg -KqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9DbGllbnQxLmNybDArBgNV -HRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkxMDEyMTkyNDMwWjALBgNVHQ8E -BAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW/O5bs8qZdIuV6kwwHQYDVR0OBBYE -FMT7nCl7l81MlvzuW7PKmXSLlepMMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA -BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7 -pFuPeJoSSJn59DXeDDYHAmsQOokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzz -wy5E97BnRqqS5TvaHBkUODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/a -EkP/TOYGJqibGapEPHayXOw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u -ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc -KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u -ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 -MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE -ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j -b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF -bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg -U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA -A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ -I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 -wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC -AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb -oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 -BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p -dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk -MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp -b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu -dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 -MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi -E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa -MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI -hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN -95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd -2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy +dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t +MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB +MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG +A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp +b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl +cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv +bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE +VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ +ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR +uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG +9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI +hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM +pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV @@ -745,75 +540,268 @@ A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y 1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT -ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw -MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j -LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ -KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo -RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu -WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw -Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD -AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK -eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM -zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ -WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN -/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== +MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMh +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIz +MloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09N +IFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11 +bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSE +RMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gO +zXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5 +bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDF +MxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1 +VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eC +OKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HW +tWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZ +q51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDb +EJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF75x3sM3Z+ +Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O +VL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj -dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0 -NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD -VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G -vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/ -BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX -MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl -IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw -NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq -y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy -0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1 -E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN +MIICPDCCAaUCEAq6HgBiMui0NiZdH3zNiWYwDQYJKoZIhvcNAQEFBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh +YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 +FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G +CSqGSIb3DQEBBQUAA4GBAIDToA+IyeVoW4R7gB+nt+MjWBEc9RTwWBKMi99x2ZAk +EXyge8N6GRm9cr0gvwA63/rVeszC42JFi8tJg5jBcGnQnl6CjDVHjk8btB9jAa3k +ltax7nosZm4XNq8afjgGhixrTcsnkm54vwDVAcCxB8MJqmSFKPKdc57PYDoKHUpI -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT -ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw -MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj -dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l -c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC -UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc -58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ -o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH -MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr -aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA -A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA -Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv -8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV +MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUx +ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 +b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQD +EytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4X +DTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJBgNVBAYTAkhVMREw +DwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9u +c2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMr +TmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA +OoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC +2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwW +RMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0P +AQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEW +ggJNRklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0 +YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFz +b2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBO +ZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2ZWRpLiBB +IGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs +b2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs +ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25s +YXBqYW4gYSBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kg +a2VyaGV0byBheiBlbGxlbm9yemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4g +SU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0 +aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQUyBhdmFpbGFibGUg +YXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwgYXQg +Y3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmY +ta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g +pO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4 +Fp1hBWeAyNDYpQcCNJgEjTME1A== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg -R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 -9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq -fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv -iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU -1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ -bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW -MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA -ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l -uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn -Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS -tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF -PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un -hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV -5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw +PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz +cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 +MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz +IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ +ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR +VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL +kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd +EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas +H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 +HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud +DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 +QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu +Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ +AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 +yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR +FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA +ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB +kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 +l7+ijrRU +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICoTCCAgqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzAN +BgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAd +BgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcNOTcwMTAxMDAwMDAwWhcN +MjAxMjMxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4g +Q2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsG +A1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1l +c3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYrWHhhRYZT +6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u6TqFJBU820cEY8OexJQa +Wt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522FOMjhdepQeBMpHmwKxqL +8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEEBQADgYEAZ9viwuaHPUCDhjc1fR/OmsMMZiCouqoEiYbC +9RAIDb/LogWK0E02PvTX72nGXuSwlG9KuefeW4i2e9vjJ+V2w/A1wcu1J5szedyQ +pgCed/r8zSeUQhac0xxo7L9c3eWpexAKMnRUEzGLhQOEkbdYATAUOK8oyvyxUBkZ +CayJSdM= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi +MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV +UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO +ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz +c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP +OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl +mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF +BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 +qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw +gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu +bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp +dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 +6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ +h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH +/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN +pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDgDCCAmigAwIBAgICAx4wDQYJKoZIhvcNAQEFBQAwYTELMAkGA1UEBhMCVVMx +DTALBgNVBAoTBFZJU0ExLzAtBgNVBAsTJlZpc2EgSW50ZXJuYXRpb25hbCBTZXJ2 +aWNlIEFzc29jaWF0aW9uMRIwEAYDVQQDEwlHUCBSb290IDIwHhcNMDAwODE2MjI1 +MTAwWhcNMjAwODE1MjM1OTAwWjBhMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklT +QTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRp +b24xEjAQBgNVBAMTCUdQIFJvb3QgMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAKkBcLWqxEDwq2omYXkZAPy/mzdZDK9vZBv42pWUJGkzEXDK41Z0ohdX +ZFwgBuHW73G3O/erwWnQSaSxBNf0V2KJXLB1LRckaeNCYOTudNargFbYiCjh+20i +/SN8RnNPflRzHqgsVVh1t0zzWkWlAhr62p3DRcMiXvOL8WAp0sdftAw6UYPvMPjU +58fy+pmjIlC++QU3o63tmsPm7IgbthknGziLgE3sucfFicv8GjLtI/C1AVj59o/g +halMCXI5Etuz9c9OYmTaxhkVOmMd6RdVoUwiPDQyRvhlV7or7zaMavrZ2UT0qt2E +1w0cslSsMoW0ZA3eQbuxNMYBhjJk1Z8CAwEAAaNCMEAwHQYDVR0OBBYEFJ59SzS/ +ca3CBfYDdYDOqU8axCRMMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQAhpXYUVfmtJ3CPPPTVbMjMCqujmAuKBiPFyWHb +mQdpNSYx/scuhMKZYdQN6X0uEyt8joW2hcdLzzW2LEc9zikv2G+fiRxkk78IvXbQ +kIqUs38oW26sTTMs7WXcFsziza6kPWKSBpUmv9+55CCmc2rBvveURNZNbyoLaxhN +dBA2aGpawWqn3TYpjLgwi08hPwAuVDAHOrqK5MOeyti12HvOdUVmB/RtLdh6yumJ +ivIj2C/LbgA2T/vwLwHMD8AiZfSr4k5hLQOCfZEWtTDVFN5ex5D8ofyrEK9ca3Cn +B+8phuiyJccg/ybdd+95RBTEvd07xQObdyPsoOy7Wjm1zK0G +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEajCCA1KgAwIBAgIBATANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJKUDEN +MAsGA1UECgwESlBLSTEpMCcGA1UECwwgUHJlZmVjdHVyYWwgQXNzb2NpYXRpb24g +Rm9yIEpQS0kxETAPBgNVBAsMCEJyaWRnZUNBMB4XDTAzMTIyNzA1MDgxNVoXDTEz +MTIyNjE0NTk1OVowWjELMAkGA1UEBhMCSlAxDTALBgNVBAoMBEpQS0kxKTAnBgNV +BAsMIFByZWZlY3R1cmFsIEFzc29jaWF0aW9uIEZvciBKUEtJMREwDwYDVQQLDAhC +cmlkZ2VDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANTnUmg7K3m8 +52vd77kwkq156euwoWm5no8E8kmaTSc7x2RABPpqNTlMKdZ6ttsyYrqREeDkcvPL +yF7yf/I8+innasNtsytcTAy8xY8Avsbd4JkCGW9dyPjk9pzzc3yLQ64Rx2fujRn2 +agcEVdPCr/XpJygX8FD5bbhkZ0CVoiASBmlHOcC3YpFlfbT1QcpOSOb7o+VdKVEi +MMfbBuU2IlYIaSr/R1nO7RPNtkqkFWJ1/nKjKHyzZje7j70qSxb+BTGcNgTHa1YA +UrogKB+UpBftmb4ds+XlkEJ1dvwokiSbCDaWFKD+YD4B2s0bvjCbw8xuZFYGhNyR +/2D5XfN1s2MCAwEAAaOCATkwggE1MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MG0GA1UdHwRmMGQwYqBgoF6kXDBaMQswCQYDVQQGEwJKUDENMAsGA1UE +CgwESlBLSTEpMCcGA1UECwwgUHJlZmVjdHVyYWwgQXNzb2NpYXRpb24gRm9yIEpQ +S0kxETAPBgNVBAsMCEJyaWRnZUNBMIGDBgNVHREEfDB6pHgwdjELMAkGA1UEBhMC +SlAxJzAlBgNVBAoMHuWFrOeahOWAi+S6uuiqjeiovOOCteODvOODk+OCuTEeMBwG +A1UECwwV6YO96YGT5bqc55yM5Y2U6K2w5LyaMR4wHAYDVQQLDBXjg5bjg6rjg4Pj +grjoqo3oqLzlsYAwHQYDVR0OBBYEFNQXMiCqQNkR2OaZmQgLtf8mR8p8MA0GCSqG +SIb3DQEBBQUAA4IBAQATjJo4reTNPC5CsvAKu1RYT8PyXFVYHbKsEpGt4GR8pDCg +HEGAiAhHSNrGh9CagZMXADvlG0gmMOnXowriQQixrtpkmx0TB8tNAlZptZWkZC+R +8TnjOkHrk2nFAEC3ezbdK0R7MR4tJLDQCnhEWbg50rf0wZ/aF8uAaVeEtHXa6W0M +Xq3dSe0XAcrLbX4zZHQTaWvdpLAIjl6DZ3SCieRMyoWUL+LXaLFdTP5WBCd+No58 +IounD9X4xxze2aeRVaiV/WnQ0OSPNS7n7YXy6xQdnaOU4KRW/Lne1EDf5IfWC/ih +bVAmhZMbcrkWWcsR6aCPG+2mV3zTD6AUzuKPal8Y +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJB +VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp +bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5R +dWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5RdWFsLTAzMB4XDTA1MDgxNzIyMDAw +MFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgwRgYDVQQKDD9BLVRy +dXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0ZW52 +ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMM +EEEtVHJ1c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCtPWFuA/OQO8BBC4SAzewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUj +lUC5B3ilJfYKvUWG6Nm9wASOhURh73+nyfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZ +znF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPESU7l0+m0iKsMrmKS1GWH +2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4iHQF63n1 +k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs +2e3Vcuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYD +VR0OBAoECERqlWdVeRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC +AQEAVdRU0VlIXLOThaq/Yy/kgM40ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fG +KOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmrsQd7TZjTXLDR8KdCoLXEjq/+ +8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZdJXDRZslo+S4R +FGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS +mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmE +DNuxUCAKGkq6ahq97BvIxYSazQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT +EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp +ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz +NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH +EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE +AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD +E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH +/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy +DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh +GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR +tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA +AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX +WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu +9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr +gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo +2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI +4uJEvlz36hz1 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILAgAAAAAA1ni3lAUwDQYJKoZIhvcNAQEEBQAwVzELMAkG @@ -837,19 +825,305 @@ ncJWWJh3w/cbrPad+D6qp1RF8PX51TFl/mtYnHGzHtdS6jIX/EBgHcl5JLL2bP2o Zg6C3ZjL2sJETy6ge/L3ayx2EYRGinij4w== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD -VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv -bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv -b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV -UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU -cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds -b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH -iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS -r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 -04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r -GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 -3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P -lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +MIIETTCCAzWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBtMQswCQYDVQQGEwJDSDEO +MAwGA1UEChMFYWRtaW4xETAPBgNVBAsTCFNlcnZpY2VzMSIwIAYDVQQLExlDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0aWVzMRcwFQYDVQQDEw5BZG1pbkNBLUNELVQwMTAe +Fw0wNjAxMjUxMzM2MTlaFw0xNjAxMjUxMjM2MTlaMG0xCzAJBgNVBAYTAkNIMQ4w +DAYDVQQKEwVhZG1pbjERMA8GA1UECxMIU2VydmljZXMxIjAgBgNVBAsTGUNlcnRp +ZmljYXRpb24gQXV0aG9yaXRpZXMxFzAVBgNVBAMTDkFkbWluQ0EtQ0QtVDAxMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0jQlMZmpLDhV+GNR9TAoSNle +JgQB4xAXJELQf5/ySMfoFA4MmjKqYXQkB6MGPuQKwR9XRRSPf61vqb8YPsdjRmgp +byHBcUd5t0N8RX6wRZUnPMW+bCCo2VqAU4XFbnlc2gHKaam0wdTtbBTXEkv0ieIH +fxCfFxXqSsSr60IkF/2/xbrAgV/QD5yHk6Ie8feAVWwi5UtaFqtu4LiFEh2QMyxs +Oyz1OcvKzkM2g873tyiE7jzMgZP+Ww3tibk2F9+e6ZeiB37TLOmVtvgpmrws4fiI +rFNXEYSWBVrUTbn81U47yWzOgf5fEHP07bRV5QOCzCm99qNimsbL6CG7nT78CQID +AQABo4H3MIH0MBIGA1UdEwEB/wQIMAYBAf8CAQAwga4GA1UdIASBpjCBozCBoAYI +YIV0AREDFQEwgZMwSAYIKwYBBQUHAgIwPBo6VGhpcyBpcyB0aGUgQWRtaW5DQS1D +RC1UMDEgQ2VydGlmaWNhdGUgUHJhY3RpY2UgU3RhdGVtZW50LjBHBggrBgEFBQcC +ARY7aHR0cDovL3d3dy5wa2kuYWRtaW4uY2gvcG9saWN5L0NQU18yXzE2Xzc1Nl8x +XzE3XzNfMjFfMS5wZGYwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQqxGkKocZV +xgNucM6GgbOkD6oZ2zANBgkqhkiG9w0BAQUFAAOCAQEAn356bbusjI5glGXRQ1DR +v21qQf0S4s3GHyZm7cqdOkFleM70ArBT+kOP5Nm7rlSAFyVgEkmBdOg7s9tlXClU +yeZFnp6UEYRUcijPN8D1VaNRK6PIUObpDBQT0C+kAfxG9z4v29T0SxT4sgAdC/xQ +Fyv58Fp9bPn7owuKwKcyCH1XSyi/Bp4XFELlLOaigBZO/w+dPBz4FcJSdZjU+BaJ +0E3nKAjHlShO5ouBSZnaJz3p+nkw2Wyo36s6GxCK0XbkSP45iniIG4FmwwZkonYF +ypQntHbx2oL7tUQQY0PDo8bGBMcPy/G2j+dciqZRlsnfgMy10SCzQ9MUx92xUG2V +eg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG +EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 +MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl +cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR +dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB +pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM +b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm +aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz +IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT +lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz +AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 +VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG +ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 +BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG +AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M +U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh +bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C ++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F +uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 +XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM +MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D +ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU +cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 +WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg +Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw +IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH +UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM +TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU +BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM +kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x +AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y +sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL +I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 +J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY +VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNV +BAMML0VCRyBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMTcwNQYDVQQKDC5FQkcgQmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXpt +ZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAeFw0wNjA4MTcwMDIxMDlaFw0xNjA4 +MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25payBTZXJ0aWZpa2Eg +SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2ltIFRl +a25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h +4fuXd7hxlugTlkaDT7byX3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAk +tiHq6yOU/im/+4mRDGSaBUorzAzu8T2bgmmkTPiab+ci2hC6X5L8GCcKqKpE+i4s +tPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfreYteIAbTdgtsApWjluTL +dlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZTqNGFav4 +c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8Um +TDGyY5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z ++kI2sSXFCjEmN1ZnuqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0O +Lna9XvNRiYuoP1Vzv9s6xiQFlpJIqkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMW +OeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vmExH8nYQKE3vwO9D8owrXieqW +fo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0Nokb+Clsi7n2 +l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgw +FoAU587GT/wWZ5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+ +8ygjdsZs93/mQJ7ANtyVDR2tFcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI +6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgmzJNSroIBk5DKd8pNSe/iWtkqvTDO +TLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64kXPBfrAowzIpAoHME +wfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqTbCmY +Iai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJn +xk1Gj7sURT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4Q +DgZxGhBM/nV+/x5XOULK1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9q +Kd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11t +hie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQY9iJSrSq3RZj9W6+YKH4 +7ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9AahH3eU7 +QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 +MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub +j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo +U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b +u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ +bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er +fF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGJDCCBY2gAwIBAgIEQoaroDANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjA3 +MTQxNzEwMjhaFw0xNDA3MTQxNzQwMjhaMFwxCzAJBgNVBAYTAlVTMRUwEwYDVQQK +EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xGzAZBgNV +BAMTEkRpZ2lDZXJ0IEdsb2JhbCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAMQ8vMy66mLmnkIjr7SyEa5ijdmh04/MFHIZ7Zn2/d5du1nAsMKvaplS +lVcLNf/hhvqvosPBBWUnIHYvClQlfOor3ZVBV5sPO89H6AEGjMVESPwHLvNygzBR +lJ5pOoOph5AU2V7EoniPwT7UGWEOGufcGpUgQb5vF9q4HEHumLD61x01PxanBCgT +XT0FdZouhp4ssBeHIFhX7+HqVWC4LHAhrCljDBD8YLz51Rw3ZNW0+x6rJjlGiKTL +zTBnwCZ55cpo+SLX5dKxu0hMmwuYW0KS5dLtDkcw+t0nVmNqpQHHjq/wTjsbVRVE +1T5NVx7hkeq4oI/OOmNflom6CD7+RLsCAwEAAaOCAwUwggMBMBIGA1UdEwEB/wQI +MAYBAf8CAQAwggEyBgNVHSAEggEpMIIBJTCCASEGCSqGSIb2fQdLAjCCARIwJgYI +KwYBBQUHAgEWGmh0dHA6Ly93d3cuZW50cnVzdC5uZXQvY3BzMIHnBggrBgEFBQcC +AjCB2hqB10ZvciB1c2Ugc29sZWx5IHdpdGggU1NMIGFuZCBTL01JTUUgY2VydGlm +aWNhdGVzIGlzc3VlZCBieSBEaWdpY2VydCwgSW5jLiB0byBhdXRob3JpemVkIHN1 +YnNjcmliZXJzLg0KRE9FUyBOT1QgcmVwcmVzZW50IGFueSBlbmRvcnNlbWVudCBi +eSBFbnRydXN0IEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMgYXMgdG8gdGhlIGlkZW50 +aXR5IG9mIGFueSBjZXJ0aWZpY2F0ZSBob2xkZXIuMDEGA1UdJQQqMCgGCCsGAQUF +BwMBBggrBgEFBQcDAgYIKwYBBQUHAwQGCCsGAQUFBwMJMIIBGAYDVR0fBIIBDzCC +AQswKKAmoCSGImh0dHA6Ly9jcmwuZW50cnVzdC5uZXQvc2VydmVyMS5jcmwwgd6g +gduggdikgdUwgdIxCzAJBgNVBAYTAlVTMRQwEgYDVQQKEwtFbnRydXN0Lm5ldDE7 +MDkGA1UECxMyd3d3LmVudHJ1c3QubmV0L0NQUyBpbmNvcnAuIGJ5IHJlZi4gKGxp +bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0 +ZWQxOjA4BgNVBAMTMUVudHJ1c3QubmV0IFNlY3VyZSBTZXJ2ZXIgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEwCwYDVR0PBAQDAgEGMB8GA1Ud +IwQYMBaAFPAXYhNVPbP/CgBr+1CEl/PtYtAaMB0GA1UdDgQWBBSnxxOgegE8ne+C +SIJI1XNRthJWKjAZBgkqhkiG9n0HQQAEDDAKGwRWNy4xAwIAgTANBgkqhkiG9w0B +AQUFAAOBgQBK8bPOaGnjWKNh7bYWyJOxGDA+4HLfTz3iTeG4/D/ByeNFqV2pwdqj +5TbXjtYPrTavbLxE5ppGlKYRoNBS59pVsPYchftjUnu2mY8f4stHZKLrCGXmUdsc +S21/U58eDTGT1DBdHm4BBydgXbvT9ONsHSAPdSozEKe3idepFxQyAw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOc +UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xS +S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg +SGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcNMDUxMTA3MTAwNzU3 +WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVrdHJv +bmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJU +UjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSw +bGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWe +LiAoYykgS2FzxLFtIDIwMDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqeLCDe2JAOCtFp0if7qnef +J1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKIx+XlZEdh +R3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJ +Qv2gQrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGX +JHpsmxcPbe9TmJEr5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1p +zpwACPI2/z7woQ8arBT9pmAPAgMBAAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58S +Fq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/nttRbj2hWyfIvwq +ECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 +Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFz +gw2lGh1uEpJ+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotH +uFEJjOp9zYhys2AzsfAKRO8P9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LS +y3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5UrbnBEI= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh +YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 +FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg +J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc +r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIETzCCAzegAwIBAgIEO63vKTANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQ +TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu +dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBS +b290Q0EwHhcNMDEwOTIzMTQxODE3WhcNMTEwOTIzMTMxODE3WjB1MQswCQYDVQQG +EwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMb +Q2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQg +LSBDQSBLbGFzYSAxMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4SRW9Q58g +5DY1Hw7hgCRKBEdPdGn0MFHsfw7rlu/oQm7IChI/uWd9q5wwo77YojtTDjRnpgZs +jqBeynX8T90vFILqsY2K5CF1OESalwvVr3sZiQX79lisuFKat92u6hBFikFIVxfH +HB67Af+g7u0dEHdDW7lwy81MwFYxBTRy9wIDAQABo4IBbTCCAWkwDwYDVR0TAQH/ +BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwggEEBgNVHSAEgfwwgfkwgfYGDSsGAQQB +vj8CAQoBAQAwgeQwgZoGCCsGAQUFBwICMIGNGoGKQ2VydHlmaWthdCB3eXN0YXdp +b255IHpnb2RuaWUgeiBkb2t1bWVudGVtOiAiUG9saXR5a2EgQ2VydHlmaWthY2pp +IGRsYSBSb290Q0EiLiBDZXJ0eWZpa2F0IHd5c3Rhd2lvbnkgcHJ6ZXogUm9vdENB +IHcgaGllcmFyY2hpaSBDQyBTaWduZXQuMEUGCCsGAQUFBwIBFjlodHRwOi8vd3d3 +LnNpZ25ldC5wbC9yZXBvenl0b3JpdW0vZG9rdW1lbnR5L3BjX3Jvb3RjYS50eHQw +HwYDVR0jBBgwFoAUwJvFIw0C4aZOSGsfAOnjmhQbsa8wHQYDVR0OBBYEFMODHtVZ +d1T7TftXR/nEI1zR54njMA0GCSqGSIb3DQEBBQUAA4IBAQBRIHQBFIGh8Jpxt87A +gSLwIEEk4+oGy769u3NtoaR0R3WNMdmt7fXTi0tyTQ9V4AIszxVjhnUPaKnF1KYy +f8Tl+YTzk9ZfFkZ3kCdSaILZAOIrmqWNLPmjUQ5/JiMGho0e1YmWUcMci84+pIis +TsytFzVP32/W+sz2H4FQAvOIMmxB7EJX9AdbnXn9EXZ+4nCqi0ft5z96ZqOJJiCB +3vSaoYg+wdkcvb6souMJzuc2uptXtR1Xf3ihlHaGW+hmnpcwFA6AoNrom6Vgzk6U +1ienx0Cw28BhRSKqzKkyXkuK8gRflZUx84uftXncwKJrMiE3lvgOOBITRzcahirL +er4c +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx +FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg +Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG +A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr +b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ +jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn +PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh +ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 +nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h +q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED +MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC +mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 +7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB +oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs +EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO +fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi +AmvZWg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe +MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v +d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh +cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn +0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ +M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a +MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd +oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI +DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy +oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 +dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy +bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF +BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli +CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE +CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t +3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS +KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBb +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qx +ETAPBgNVBAsTCERTVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0w +MzExMjAyMTE5NThaFw0xNzExMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYD +VQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UECxMIRFNUIEFDRVMx +FzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPu +ktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7 +gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH +fAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4a +ahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEIT +ajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rk +c3QuY29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjto +dHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMt +aW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZI +hvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99Pe7lv7Uk +QIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/ +h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq +nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpR +rscL9yuwNwXsvFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf2 +9w4LTJxoeHtxMcfrHuBnQfO3oKfN5XozNmr6mis= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARwxCzAJBgNVBAYTAkVT @@ -897,950 +1171,6 @@ HnNDJGD1HWHc3JagvPsd4+cSACczAsDAK1M92GsDgaPb1pOVIO/Tln4mkImcJpvN b2ar7QMiRDjMWb2f2/YHogF/JsRj9SVCXmK9 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIH6jCCB1OgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl -SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl -SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 -DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAwNTkzOFoXDTI1MTIyNzAw -NTkzOFowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD -VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n -IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g -IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4FEnpwvdr9G5Q1uCN0VWcu+atsIS7ywS -zHb5BlmvXSHU0lq4oNTzav3KaY1mSPd05u42veiWkXWmcSjK5yISMmmwPh5r9FBS -YmL9Yzt9fuzuOOpi9GyocY3h6YvJP8a1zZRCb92CRTzo3wno7wpVqVZHYUxJZHMQ -KD/Kvwn/xi8CAwEAAaOCBEowggRGMB0GA1UdDgQWBBTrsxl588GlHKzcuh9morKb -adB4CDCCAUQGA1UdIwSCATswggE3gBTrsxl588GlHKzcuh9morKbadB4CKGCARqk -ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE -BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT -ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC -LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD -VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr -BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB -FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC -AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB -D2lwc0BtYWlsLmlwcy5lczBBBglghkgBhvhCAQ0ENBYyQ0xBU0UxIENBIENlcnRp -ZmljYXRlIGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgEC -BBwWGmh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDoGCWCGSAGG+EIBBAQtFito -dHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEuY3JsMD8GCWCG -SAGG+EIBAwQyFjBodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25D -TEFTRTEuaHRtbD8wPAYJYIZIAYb4QgEHBC8WLWh0dHA6Ly93d3cuaXBzLmVzL2lw -czIwMDIvcmVuZXdhbENMQVNFMS5odG1sPzA6BglghkgBhvhCAQgELRYraHR0cDov -L3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTEuaHRtbDBzBgNVHR8EbDBq -MDGgL6AthitodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEu -Y3JsMDWgM6Axhi9odHRwOi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy -Q0xBU0UxLmNybDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9v -Y3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQADgYEAK9Dr/drIyllq2tPMMi7JVBuK -Yn4VLenZMdMu9Ccj/1urxUq2ckCuU3T0vAW0xtnIyXf7t/k0f3gA+Nak5FI/LEpj -V4F1Wo7ojPsCwJTGKbqz3Bzosq/SLmJbGqmODszFV0VRFOlOHIilkfSj945RyKm+ -hjM+5i9Ibq9UkE6tsSU= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH6jCCB1OgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl -SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl -SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 -DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAxMDE0NFoXDTI1MTIyNzAx -MDE0NFowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD -VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n -IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g -IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqxf+DrDGaBtT8FK+n/ra+osTBLsBjzLZ -H49NzjaY2uQARIwo2BNEKqRrThckQpzTiKRBgtYj+4vJhuW5qYIF3PHeH+AMmVWY -8jjsbJ0gA8DvqqPGZARRLXgNo9KoOtYkTOmWehisEyMiG3zoMRGzXwmqMHBxRiVr -SXGAK5UBsh8CAwEAAaOCBEowggRGMB0GA1UdDgQWBBS4k/8uy9wsjqLnev42USGj -mFsMNDCCAUQGA1UdIwSCATswggE3gBS4k/8uy9wsjqLnev42USGjmFsMNKGCARqk -ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE -BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT -ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC -LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD -VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr -BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB -FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC -AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB -D2lwc0BtYWlsLmlwcy5lczBBBglghkgBhvhCAQ0ENBYyQ0xBU0UzIENBIENlcnRp -ZmljYXRlIGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgEC -BBwWGmh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDoGCWCGSAGG+EIBBAQtFito -dHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMuY3JsMD8GCWCG -SAGG+EIBAwQyFjBodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25D -TEFTRTMuaHRtbD8wPAYJYIZIAYb4QgEHBC8WLWh0dHA6Ly93d3cuaXBzLmVzL2lw -czIwMDIvcmVuZXdhbENMQVNFMy5odG1sPzA6BglghkgBhvhCAQgELRYraHR0cDov -L3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTMuaHRtbDBzBgNVHR8EbDBq -MDGgL6AthitodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMu -Y3JsMDWgM6Axhi9odHRwOi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy -Q0xBU0UzLmNybDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9v -Y3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQADgYEAF2VcmZVDAyevJuXr0LMXI/dD -qsfwfewPxqmurpYPdikc4gYtfibFPPqhwYHOU7BC0ZdXGhd+pFFhxu7pXu8Fuuu9 -D6eSb9ijBmgpjnn1/7/5p6/ksc7C0YBCJwUENPjDfxZ4IwwHJPJGR607VNCv1TGy -r33I6unUVtkOE7LFRVA= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm -SVBTIENBIENMQVNFQTEgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT -JklQUyBDQSBDTEFTRUExIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI -hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjI5MDEwNTMyWhcNMjUxMjI3 -MDEwNTMyWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw -gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALsw19zQVL01Tp/FTILq0VA8R5j8 -m2mdd81u4D/u6zJfX5/S0HnllXNEITLgCtud186Nq1KLK3jgm1t99P1tCeWu4Wwd -ByOgF9H5fahGRpEiqLJpxq339fWUoTCUvQDMRH/uxJ7JweaPCjbB/SQ9AaD1e+J8 -eGZDi09Z8pvZ+kmzAgMBAAGjggRTMIIETzAdBgNVHQ4EFgQUZyaW56G/2LUDnf47 -3P7yiuYV3TAwggFGBgNVHSMEggE9MIIBOYAUZyaW56G/2LUDnf473P7yiuYV3TCh -ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC -AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF -BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB -BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg -hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud -EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0VBMSBD -QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cDovL3d3dy5pcHMuZXMvMCkGCWCG -SAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyLzA7BglghkgBhvhC -AQQELhYsaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VBMS5j -cmwwQAYJYIZIAYb4QgEDBDMWMWh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2 -b2NhdGlvbkNMQVNFQTEuaHRtbD8wPQYJYIZIAYb4QgEHBDAWLmh0dHA6Ly93d3cu -aXBzLmVzL2lwczIwMDIvcmVuZXdhbENMQVNFQTEuaHRtbD8wOwYJYIZIAYb4QgEI -BC4WLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VBMS5odG1s -MHUGA1UdHwRuMGwwMqAwoC6GLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvaXBz -MjAwMkNMQVNFQTEuY3JsMDagNKAyhjBodHRwOi8vd3d3YmFjay5pcHMuZXMvaXBz -MjAwMi9pcHMyMDAyQ0xBU0VBMS5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF -BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAH66iqyA -AIQVCtWYUQxkxZwCWINmyq0eB81+atqAB98DNEock8RLWCA1NnHtogo1EqWmZaeF -aQoO42Hu6r4okzPV7Oi+xNtff6j5YzHIa5biKcJboOeXNp13XjFr/tOn2yrb25aL -H2betgPAK7N41lUH5Y85UN4HI3LmvSAUS7SG ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm -SVBTIENBIENMQVNFQTMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT -JklQUyBDQSBDTEFTRUEzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI -hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjI5MDEwNzUwWhcNMjUxMjI3 -MDEwNzUwWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw -gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO6AAPYaZC6tasiDsYun7o/ZttvN -G7uGBiJ2MwwSbUhWYdLcgiViL5/SaTBlA0IjWLxH3GvWdV0XPOH/8lhneaDBgbHU -VqLyjRGZ/fZ98cfEXgIqmuJKtROKAP2Md4bm15T1IHUuDky/dMQ/gT6DtKM4Ninn -6Cr1jIhBqoCm42zvAgMBAAGjggRTMIIETzAdBgNVHQ4EFgQUHp9XUEe2YZM50yz8 -2l09BXW3mQIwggFGBgNVHSMEggE9MIIBOYAUHp9XUEe2YZM50yz82l09BXW3mQKh -ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC -AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF -BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB -BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg -hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud -EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0VBMyBD -QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cDovL3d3dy5pcHMuZXMvMCkGCWCG -SAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyLzA7BglghkgBhvhC -AQQELhYsaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VBMy5j -cmwwQAYJYIZIAYb4QgEDBDMWMWh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2 -b2NhdGlvbkNMQVNFQTMuaHRtbD8wPQYJYIZIAYb4QgEHBDAWLmh0dHA6Ly93d3cu -aXBzLmVzL2lwczIwMDIvcmVuZXdhbENMQVNFQTMuaHRtbD8wOwYJYIZIAYb4QgEI -BC4WLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VBMy5odG1s -MHUGA1UdHwRuMGwwMqAwoC6GLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvaXBz -MjAwMkNMQVNFQTMuY3JsMDagNKAyhjBodHRwOi8vd3d3YmFjay5pcHMuZXMvaXBz -MjAwMi9pcHMyMDAyQ0xBU0VBMy5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF -BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAEo9IEca -2on0eisxeewBwMwB9dbB/MjD81ACUZBYKp/nNQlbMAqBACVHr9QPDp5gJqiVp4MI -3y2s6Q73nMify5NF8bpqxmdRSmlPa/59Cy9SKcJQrSRE7SOzSMtEQMEDlQwKeAYS -AfWRMS1Jjbs/RU4s4OjNtckUFQzjB4ObJnXv ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIIODCCB6GgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCAR4xCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjE0MDIGA1UECxMr -SVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE0MDIG -A1UEAxMrSVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eTEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAxMTAx -OFoXDTI1MTIyNzAxMTAxOFowggEeMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFy -Y2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5l -dCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlw -cy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxNDAyBgNVBAsTK0lQUyBDQSBUaW1lc3Rh -bXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxNDAyBgNVBAMTK0lQUyBDQSBU -aW1lc3RhbXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHjAcBgkqhkiG9w0B -CQEWD2lwc0BtYWlsLmlwcy5lczCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA -vLjuVqWajOY2ycJioGaBjRrVetJznw6EZLqVtJCneK/K/lRhW86yIFcBrkSSQxA4 -Efdo/BdApWgnMjvEp+ZCccWZ73b/K5Uk9UmSGGjKALWkWi9uy9YbLA1UZ2t6KaFY -q6JaANZbuxjC3/YeE1Z2m6Vo4pjOxgOKNNtMg0GmqaMCAwEAAaOCBIAwggR8MB0G -A1UdDgQWBBSL0BBQCYHynQnVDmB4AyKiP8jKZjCCAVAGA1UdIwSCAUcwggFDgBSL -0BBQCYHynQnVDmB4AyKiP8jKZqGCASakggEiMIIBHjELMAkGA1UEBhMCRVMxEjAQ -BgNVBAgTCUJhcmNlbG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJ -UFMgSW50ZXJuZXQgcHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJp -cHNAbWFpbC5pcHMuZXMgQy5JLkYuICBCLTYwOTI5NDUyMTQwMgYDVQQLEytJUFMg -Q0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTQwMgYDVQQD -EytJUFMgQ0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4w -HAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAM -BgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYB -BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIB -FgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYD -VR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlw -cy5lczBHBglghkgBhvhCAQ0EOhY4VGltZXN0YW1waW5nIENBIENlcnRpZmljYXRl -IGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgECBBwWGmh0 -dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMEAGCWCGSAGG+EIBBAQzFjFodHRwOi8v -d3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMEUGCWCG -SAGG+EIBAwQ4FjZodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25U -aW1lc3RhbXBpbmcuaHRtbD8wQgYJYIZIAYb4QgEHBDUWM2h0dHA6Ly93d3cuaXBz -LmVzL2lwczIwMDIvcmVuZXdhbFRpbWVzdGFtcGluZy5odG1sPzBABglghkgBhvhC -AQgEMxYxaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lUaW1lc3RhbXBp -bmcuaHRtbDB/BgNVHR8EeDB2MDegNaAzhjFodHRwOi8vd3d3Lmlwcy5lcy9pcHMy -MDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMDugOaA3hjVodHRwOi8vd3d3YmFj -ay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyVGltZXN0YW1waW5nLmNybDAvBggrBgEF -BQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZI -hvcNAQEFBQADgYEAZbrBzAAalZHK6Ww6vzoeFAh8+4Pua2JR0zORtWB5fgTYXXk3 -6MNbsMRnLWhasl8OCvrNPzpFoeo2zyYepxEoxZSPhExTCMWTs/zif/WN87GphV+I -3pGW7hdbrqXqcGV4LCFkAZXOzkw+UPS2Wctjjba9GNSHSl/c7+lW8AoM6HU= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz -MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw -IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR -dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp -li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D -rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ -WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug -F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU -xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC -Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv -dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw -ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl -IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh -c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy -ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh -Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI -KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T -KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq -y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p -dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD -VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL -MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk -fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 -7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R -cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y -mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW -xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK -SnQ2+Q== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy -NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD -cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs -2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY -JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE -Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ -n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A -PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICXDCCAcWgAwIBAgIQCgEBAQAAAnwAAAALAAAAAjANBgkqhkiG9w0BAQUFADA6 -MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp -dHkgMTAyNCBWMzAeFw0wMTAyMjIyMTAxNDlaFw0yNjAyMjIyMDAxNDlaMDoxGTAX -BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAx -MDI0IFYzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDV3f5mCc8kPD6ugU5O -isRpgFtZO9+5TUzKtS3DJy08rwBCbbwoppbPf9dYrIMKo1W1exeQFYRMiu4mmdxY -78c4pqqv0I5CyGLXq6yp+0p9v+r+Ek3d/yYtbzZUaMjShFbuklNhCbM/OZuoyZu9 -zp9+1BlqFikYvtc6adwlWzMaUQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBTEwBykB5T9zU0B1FTapQxf3q4FWjAd -BgNVHQ4EFgQUxMAcpAeU/c1NAdRU2qUMX96uBVowDQYJKoZIhvcNAQEFBQADgYEA -Py1q4yZDlX2Jl2X7deRyHUZXxGFraZ8SmyzVWujAovBDleMf6XbN3Ou8k6BlCsdN -T1+nr6JGFLkM88y9am63nd4lQtBU/55oc2PcJOsiv6hy8l4A4Q1OOkNumU4/iXgD -mMrzVcydro7BqkWY+o8aoI2II/EVQQ2lRj6RP4vr93E= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6 -MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp -dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX -BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy -MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp -eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg -/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl -wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh -AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2 -PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu -AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR -MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc -HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/ -Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+ -f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO -rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch -6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3 -7CAFYd4= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY -MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t -dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 -WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD -VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 -9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ -DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 -Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N -QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ -xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G -A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG -kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr -Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 -Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU -JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot -RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP -MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAx -MDQwNjEwNDkxM1oXDTIxMDQwNjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNV -BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMSBDQTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H887dF+2rDNbS82rDTG -29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9EJUk -oVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk -3w0LBUXl0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBL -qdReLjVQCfOAl/QMF6452F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIIN -nvmLVz5MxxftLItyM19yejhW1ebZrgUaHXVFsculJRwSVzb9IjcCAwEAAaMzMDEw -DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZTiFIwCwYDVR0PBAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE928Jj2VuX -ZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0H -DjxVyhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VO -TzF2nBBhjrZTOqMRvq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2Uv -kVrCqIexVmiUefkl98HVrhq4uz2PqYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4w -zMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9ZIRlXvVWa ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP -MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx -MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV -BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o -Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt -5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s -3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej -vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu -8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw -DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil -zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ -3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD -FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 -Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 -ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJO -TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFh -dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEy -MTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVk -ZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENB -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFtvszn -ExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw71 -9tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MO -hXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U -tFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3o -BmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAh -SQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDww -OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMv -cm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA -7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k -/rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzm -eafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0C5GUR5z6 -u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy -7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR -iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJE -SzEVMBMGA1UEChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQg -Um9vdCBDQTAeFw0wMTA0MDUxNjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNV -BAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJuZXQxHTAbBgNVBAsTFFREQyBJbnRl -cm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLhA -vJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20jxsNu -Zp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a -0vnRrEvLznWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc1 -4izbSysseLlJ28TQx5yc5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGN -eGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcD -R0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZIAYb4QgEBBAQDAgAHMGUG -A1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMMVERDIElu -dGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxME -Q1JMMTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3 -WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAw -HQYDVR0OBBYEFGxkAcf9hW2syNqeUAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJ -KoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQBO -Q8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540mgwV5dOy0uaOX -wTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ -2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm89 -9qNLPg7kbWzbO0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0 -jUNAE4z9mQNUecYu6oah9jrUCbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38 -aQNiuJkFBT1reBK9sG9l ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJE -SzEMMAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEw -ODM5MzBaFw0zNzAyMTEwOTA5MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNU -REMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuHnEz9pPPEXyG9VhDr -2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0zY0s -2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItU -GBxIYXvViGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKj -dGqPqcNiKXEx5TukYBdedObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+r -TpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/ -BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB5DCB4TCB3gYIKoFQgSkB -AQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5kay9yZXBv -c2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRl -ciBmcmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEu -MS4xLiBDZXJ0aWZpY2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIg -T0lEIDEuMi4yMDguMTY5LjEuMS4xLjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1Ud -HwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEMMAoGA1UEChMDVERDMRQwEgYD -VQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYmaHR0cDovL2Ny -bC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy -MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZ -J2cdUBVLc647+RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqG -SIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACrom -JkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4A9G28kNBKWKnctj7fAXmMXAnVBhO -inxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYscA+UYyAFMP8uXBV2Y -caaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9AOoB -mbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQ -YqbsFbS1AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9 -BKNDLdr8C2LqL19iUw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD -VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT -ZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBlcnNvbmFsIEJhc2lj -IENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNpY0B0aGF3dGUuY29tMB4X -DTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgcsxCzAJBgNVBAYTAlpBMRUw -EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE -ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy -dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBD -QTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53 -dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdK -wPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7 -G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQF -AAOBgQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7 -c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95B21P -9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD -VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT -ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt -YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu -Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT -AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa -MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp -b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG -cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh -d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY -DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E -rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq -uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN -BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP -MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa -/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei -gQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD -VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT -ZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBlcnNvbmFsIFByZW1p -dW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXByZW1pdW1AdGhhd3RlLmNv -bTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5NTlaMIHPMQswCQYDVQQGEwJa -QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY -BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u -IFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJl -bWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUu -Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0Vs -Bd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWI -Et12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYD -ZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG -SIb3DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH -b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVxeTBh -KXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1KzGJ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD -VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy -dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t -MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB -MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG -A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp -b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl -cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv -bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE -VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ -ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR -uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG -9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI -hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM -pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD -VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm -MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx -MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT -DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 -dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl -cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 -DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD -gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 -yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX -L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj -EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG -7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e -QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ -qdq5snUb9kLy78fyGPmJvKP/iiMucEc= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICoTCCAgqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzAN -BgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAd -BgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcNOTcwMTAxMDAwMDAwWhcN -MjAxMjMxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4g -Q2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsG -A1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1l -c3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYrWHhhRYZT -6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u6TqFJBU820cEY8OexJQa -Wt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522FOMjhdepQeBMpHmwKxqL -8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB -Af8wDQYJKoZIhvcNAQEEBQADgYEAZ9viwuaHPUCDhjc1fR/OmsMMZiCouqoEiYbC -9RAIDb/LogWK0E02PvTX72nGXuSwlG9KuefeW4i2e9vjJ+V2w/A1wcu1J5szedyQ -pgCed/r8zSeUQhac0xxo7L9c3eWpexAKMnRUEzGLhQOEkbdYATAUOK8oyvyxUBkZ -CayJSdM= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG -EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD -VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu -dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 -E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ -D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK -4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq -lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW -bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB -o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT -MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js -LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr -BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB -AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj -j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH -KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv -2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 -mfnGV/TJVTl4uix5yaaIK/QI ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCB -rjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0BgNVBAMTLVVUTi1VU0VSRmlyc3Qt -Q2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05OTA3MDkxNzI4NTBa -Fw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAV -BgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l -dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UE -AxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3B -YHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9 -hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8om+rWV6l -L8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLm -SGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM -1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws -6wIDAQABo4G5MIG2MAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud -DgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNVHR8EUTBPME2gS6BJhkdodHRw -Oi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGllbnRBdXRoZW50 -aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH -AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u -7mFVbwQ+zznexRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0 -xtcgBEXkzYABurorbs6q15L+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQ -rfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarVNZ1yQAOJujEdxRBoUp7fooXFXAim -eOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZw7JHpsIyYdfHb0gk -USeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB -lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt -SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG -A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe -MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v -d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh -cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn -0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ -M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a -MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd -oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI -DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy -oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 -dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy -bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF -BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM -//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli -CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE -CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t -3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS -KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCB -ozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3Qt -TmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5WhcNMTkwNzA5MTg1 -NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0 -IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYD -VQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VS -Rmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB -DwAwggEKAoIBAQCz+5Gh5DZVhawGNFugmliy+LUPBXeDrjKxdpJo7CNKyXY/45y2 -N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4CjDUeJT1FxL+78P/m4FoCH -iZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXuOzr0hARe -YFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1 -axwiP8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6g -yN7igEL66S/ozjIEj3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQD -AgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPh -ahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9V -VE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0GCSqGSIb3DQEB -BQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y -IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6Lzs -QCv4AdRWOOTKRIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4 -ZSfP1FMa8Kxun08FDAOBp4QpxFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qM -YEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAqDbUMo2s/rn9X9R+WfN9v3YIwLGUb -QErNaLly7HF27FSOH4UMAWr6pjisH8SE ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCB -lTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAbBgNVBAMTFFVUTi1VU0VSRmlyc3Qt -T2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAzNlowgZUxCzAJBgNV -BAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxHjAc -BgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3 -dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicP -HxzfOpuCaDDASmEd8S8O+r5596Uj71VRloTN2+O5bj4x2AogZ8f02b+U60cEPgLO -KqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQw5ujm9M89RKZd7G3CeBo -5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vulBe3/IW+ -pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehb -kkj7RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUC -AwEAAaOBrzCBrDALBgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -FgQU2u1kdBScFDyr3ZmpvVsoTYs8ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov -L2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0LmNybDApBgNV -HSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQwDQYJKoZIhvcN -AQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw -NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXB -mMiKVl0+7kNOPmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU -4U3GDZlDAQ0Slox4nb9QorFEqmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK5 -81OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCGhU3IfdeLA/5u1fedFqySLKAj5ZyR -Uh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy -NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y -LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ -TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y -TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 -LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW -I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw -nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy -NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY -dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 -WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS -v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v -UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu -IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC -W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh -c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05 -NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD -VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp -bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB -jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N -H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR -4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN -BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo -EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5 -FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx -lA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK -VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm -Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J -h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul -uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68 -DzFc6PLZ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 -nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO -8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV -ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb -PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 -6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr -n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a -qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 -wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 -ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs -pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 -E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh -YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 -FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G -CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg -J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc -r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns -YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH -MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y -aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe -Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX -MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj -IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx -KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s -eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM -HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw -DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC -AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji -nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX -rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn -jBJ7xUS0rg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy -aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s -IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp -Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV -BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp -Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu -Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g -Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt -IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU -J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO -JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY -wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o -koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN -qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E -Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe -xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u -7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU -sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI -sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP -cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE -BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is -I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G -CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do -lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc -AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 -pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 -13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk -U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i -F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY -oJ2daZH9 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b -N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t -KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu -kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm -CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ -Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu -imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te -2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe -DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC -/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p -F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt -TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM -HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK -qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj -cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y -cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP -T8qAkbYp ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 -GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ -+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd -U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm -NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY -ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ -ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 -CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq -g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm -fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c -2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ -bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv @@ -1863,136 +1193,186 @@ LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd 398znM/jra6O1I7mT1GvFpLgXPYHDw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDgDCCAmigAwIBAgICAx4wDQYJKoZIhvcNAQEFBQAwYTELMAkGA1UEBhMCVVMx -DTALBgNVBAoTBFZJU0ExLzAtBgNVBAsTJlZpc2EgSW50ZXJuYXRpb25hbCBTZXJ2 -aWNlIEFzc29jaWF0aW9uMRIwEAYDVQQDEwlHUCBSb290IDIwHhcNMDAwODE2MjI1 -MTAwWhcNMjAwODE1MjM1OTAwWjBhMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklT -QTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRp -b24xEjAQBgNVBAMTCUdQIFJvb3QgMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAKkBcLWqxEDwq2omYXkZAPy/mzdZDK9vZBv42pWUJGkzEXDK41Z0ohdX -ZFwgBuHW73G3O/erwWnQSaSxBNf0V2KJXLB1LRckaeNCYOTudNargFbYiCjh+20i -/SN8RnNPflRzHqgsVVh1t0zzWkWlAhr62p3DRcMiXvOL8WAp0sdftAw6UYPvMPjU -58fy+pmjIlC++QU3o63tmsPm7IgbthknGziLgE3sucfFicv8GjLtI/C1AVj59o/g -halMCXI5Etuz9c9OYmTaxhkVOmMd6RdVoUwiPDQyRvhlV7or7zaMavrZ2UT0qt2E -1w0cslSsMoW0ZA3eQbuxNMYBhjJk1Z8CAwEAAaNCMEAwHQYDVR0OBBYEFJ59SzS/ -ca3CBfYDdYDOqU8axCRMMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQAhpXYUVfmtJ3CPPPTVbMjMCqujmAuKBiPFyWHb -mQdpNSYx/scuhMKZYdQN6X0uEyt8joW2hcdLzzW2LEc9zikv2G+fiRxkk78IvXbQ -kIqUs38oW26sTTMs7WXcFsziza6kPWKSBpUmv9+55CCmc2rBvveURNZNbyoLaxhN -dBA2aGpawWqn3TYpjLgwi08hPwAuVDAHOrqK5MOeyti12HvOdUVmB/RtLdh6yumJ -ivIj2C/LbgA2T/vwLwHMD8AiZfSr4k5hLQOCfZEWtTDVFN5ex5D8ofyrEK9ca3Cn -B+8phuiyJccg/ybdd+95RBTEvd07xQObdyPsoOy7Wjm1zK0G +MIIH8jCCB1ugAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl +SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl +SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 +DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIzMTExMTkzMVoXDTI1MTIyOTEx +MTkzMVowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD +VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n +IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g +IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAve2QhYLxoN2P3DVo4Xw+6Gyb2vDjfzvB +JRvH+WFIXO3KItC1dJk2W7iFnsZJnb65Q6NDKxhwfQ4XnLuBSPqMVJ6EHB++I1p2 +pg0j7YOtec++o3ysS6zf1r01HSh8i85+AcGcgLO4Z79w9jtEGlSdrFhCLUjJJSEs +XdzSbkEFrkMCAwEAAaOCBFIwggROMB0GA1UdDgQWBBT7o4z3Z4tAqk02rzCA6po7 +4C9o6DCCAUQGA1UdIwSCATswggE3gBT7o4z3Z4tAqk02rzCA6po74C9o6KGCARqk +ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE +BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT +ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC +LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD +VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr +BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB +FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC +AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB +D2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0UzIENBIENlcnRp +ZmljYXRlIGlzc3VlZCBieSBodHRwczovL3d3dy5pcHMuZXMvMCoGCWCGSAGG+EIB +AgQdFhtodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi8wOwYJYIZIAYb4QgEEBC4W +LGh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMuY3JsMEAG +CWCGSAGG+EIBAwQzFjFodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9yZXZvY2F0 +aW9uQ0xBU0UzLmh0bWw/MD0GCWCGSAGG+EIBBwQwFi5odHRwczovL3d3dy5pcHMu +ZXMvaXBzMjAwMi9yZW5ld2FsQ0xBU0UzLmh0bWw/MDsGCWCGSAGG+EIBCAQuFixo +dHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTMuaHRtbDB1BgNV +HR8EbjBsMDKgMKAuhixodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy +Q0xBU0UzLmNybDA2oDSgMoYwaHR0cHM6Ly93d3diYWNrLmlwcy5lcy9pcHMyMDAy +L2lwczIwMDJDTEFTRTMuY3JsMC8GCCsGAQUFBwEBBCMwITAfBggrBgEFBQcwAYYT +aHR0cDovL29jc3AuaXBzLmVzLzANBgkqhkiG9w0BAQUFAAOBgQAiu2FuR8MoQlYw +3QtFc/BI7DgkUUeSIM49JoMU0H3a4Y+JbQxQ4q/n6yAbEuMETUyqob/HmS/NkLJq +ur3RvGBseDXgxNyePGjFc97ITNWf5X1+4CXtBf+TTKNEMg1UpPbCz+9EkjzTcYj1 +5tjLbAp/mmLLZmCOV7cCGuXGSTBNzA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIETzCCAzegAwIBAgIEO63vKTANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBS -b290Q0EwHhcNMDEwOTIzMTQxODE3WhcNMTEwOTIzMTMxODE3WjB1MQswCQYDVQQG -EwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMb -Q2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQg -LSBDQSBLbGFzYSAxMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4SRW9Q58g -5DY1Hw7hgCRKBEdPdGn0MFHsfw7rlu/oQm7IChI/uWd9q5wwo77YojtTDjRnpgZs -jqBeynX8T90vFILqsY2K5CF1OESalwvVr3sZiQX79lisuFKat92u6hBFikFIVxfH -HB67Af+g7u0dEHdDW7lwy81MwFYxBTRy9wIDAQABo4IBbTCCAWkwDwYDVR0TAQH/ -BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwggEEBgNVHSAEgfwwgfkwgfYGDSsGAQQB -vj8CAQoBAQAwgeQwgZoGCCsGAQUFBwICMIGNGoGKQ2VydHlmaWthdCB3eXN0YXdp -b255IHpnb2RuaWUgeiBkb2t1bWVudGVtOiAiUG9saXR5a2EgQ2VydHlmaWthY2pp -IGRsYSBSb290Q0EiLiBDZXJ0eWZpa2F0IHd5c3Rhd2lvbnkgcHJ6ZXogUm9vdENB -IHcgaGllcmFyY2hpaSBDQyBTaWduZXQuMEUGCCsGAQUFBwIBFjlodHRwOi8vd3d3 -LnNpZ25ldC5wbC9yZXBvenl0b3JpdW0vZG9rdW1lbnR5L3BjX3Jvb3RjYS50eHQw -HwYDVR0jBBgwFoAUwJvFIw0C4aZOSGsfAOnjmhQbsa8wHQYDVR0OBBYEFMODHtVZ -d1T7TftXR/nEI1zR54njMA0GCSqGSIb3DQEBBQUAA4IBAQBRIHQBFIGh8Jpxt87A -gSLwIEEk4+oGy769u3NtoaR0R3WNMdmt7fXTi0tyTQ9V4AIszxVjhnUPaKnF1KYy -f8Tl+YTzk9ZfFkZ3kCdSaILZAOIrmqWNLPmjUQ5/JiMGho0e1YmWUcMci84+pIis -TsytFzVP32/W+sz2H4FQAvOIMmxB7EJX9AdbnXn9EXZ+4nCqi0ft5z96ZqOJJiCB -3vSaoYg+wdkcvb6souMJzuc2uptXtR1Xf3ihlHaGW+hmnpcwFA6AoNrom6Vgzk6U -1ienx0Cw28BhRSKqzKkyXkuK8gRflZUx84uftXncwKJrMiE3lvgOOBITRzcahirL -er4c +MIIG0zCCBbugAwIBAgIBADANBgkqhkiG9w0BAQUFADCBzDELMAkGA1UEBhMCQVQx +EDAOBgNVBAgTB0F1c3RyaWExDzANBgNVBAcTBlZpZW5uYTE6MDgGA1UEChMxQVJH +RSBEQVRFTiAtIEF1c3RyaWFuIFNvY2lldHkgZm9yIERhdGEgUHJvdGVjdGlvbjEl +MCMGA1UECxMcQS1DRVJUIENlcnRpZmljYXRpb24gU2VydmljZTEYMBYGA1UEAxMP +QS1DRVJUIEFEVkFOQ0VEMR0wGwYJKoZIhvcNAQkBFg5pbmZvQGEtY2VydC5hdDAe +Fw0wNDEwMjMxNDE0MTRaFw0xMTEwMjMxNDE0MTRaMIHMMQswCQYDVQQGEwJBVDEQ +MA4GA1UECBMHQXVzdHJpYTEPMA0GA1UEBxMGVmllbm5hMTowOAYDVQQKEzFBUkdF +IERBVEVOIC0gQXVzdHJpYW4gU29jaWV0eSBmb3IgRGF0YSBQcm90ZWN0aW9uMSUw +IwYDVQQLExxBLUNFUlQgQ2VydGlmaWNhdGlvbiBTZXJ2aWNlMRgwFgYDVQQDEw9B +LUNFUlQgQURWQU5DRUQxHTAbBgkqhkiG9w0BCQEWDmluZm9AYS1jZXJ0LmF0MIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3euXIy+mnf6BYKbK+QH5k679 +tUFqeT8jlZxMew8eNiHuw9KoxWBzL6KksK+5uK7Gatw+sbAYntEGE80P+Jg1hADM +e+Fr5V0bc6QS3gkVtfUCW/RIvfMM39oxvmqJmOgPnJU7H6+nmLtsq61tv9kVJi/2 +4Y5wXW3odet72sF57EoG6s78w0BUVLNcMngS9bZZzmdG3/d6JbkGgoNF/8DcgCBJ +W/t0JrcIzyppXIOVtUzzOrrU86zuUgT3Rtkl5kjG7DEHpFb9H0fTOY1v8+gRoaO6 +2gA0PCiysgVZjwgVeYe3KAg11nznyleDv198uK3Dc1oXIGYjJx2FpKWUvAuAEwID +AQABo4ICvDCCArgwHQYDVR0OBBYEFDd/Pj6ZcWDKJNSRE3nQdCm0qCTYMIH5BgNV +HSMEgfEwge6AFDd/Pj6ZcWDKJNSRE3nQdCm0qCTYoYHSpIHPMIHMMQswCQYDVQQG +EwJBVDEQMA4GA1UECBMHQXVzdHJpYTEPMA0GA1UEBxMGVmllbm5hMTowOAYDVQQK +EzFBUkdFIERBVEVOIC0gQXVzdHJpYW4gU29jaWV0eSBmb3IgRGF0YSBQcm90ZWN0 +aW9uMSUwIwYDVQQLExxBLUNFUlQgQ2VydGlmaWNhdGlvbiBTZXJ2aWNlMRgwFgYD +VQQDEw9BLUNFUlQgQURWQU5DRUQxHTAbBgkqhkiG9w0BCQEWDmluZm9AYS1jZXJ0 +LmF0ggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgHmMEcGA1UdJQRAMD4G +CCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcD +CAYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAP8wUQYDVR0gBEowSDBGBggq +KAAYAQEBAzA6MDgGCCsGAQUFBwIBFixodHRwOi8vd3d3LmEtY2VydC5hdC9jZXJ0 +aWZpY2F0ZS1wb2xpY3kuaHRtbDA7BglghkgBhvhCAQgELhYsaHR0cDovL3d3dy5h +LWNlcnQuYXQvY2VydGlmaWNhdGUtcG9saWN5Lmh0bWwwGQYDVR0RBBIwEIEOaW5m +b0BhLWNlcnQuYXQwLwYDVR0SBCgwJoEOaW5mb0BhLWNlcnQuYXSGFGh0dHA6Ly93 +d3cuYS1jZXJ0LmF0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHBzOi8vc2VjdXJlLmEt +Y2VydC5hdC9jZ2ktYmluL2EtY2VydC1hZHZhbmNlZC5jZ2kwDQYJKoZIhvcNAQEF +BQADggEBACX1IvgfdG2rvfv35O48vSEvcVaEdlN8USFBHWz3JRAozgzvaBtwHkjK +Zwt5l/BWOtjbvHfRjDt7ijlBEcxOOrNC1ffyMHwHrXpvff6YpQ5wnxmIYEQcURiG +HMqruEX0WkuDNgSKwefsgXs27eeBauHgNGVcTYH1rmHu/ZyLpLxOyJQ2PCzA1DzW +3rWkIX92ogJ7lTRdWrbxwUL1XGinxnnaQ74+/y0pI9JNEv7ic2tpkweRMpkedaLW +msC1+orfKTebsg69aMaCx7o6jNONRmR/7TVaPf8/k6g52cHZ9YWjQvup22b5rWxG +J5r5LZ4vCPmF4+T4lutjUYAa/lGuQTg= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIE9zCCA9+gAwIBAgIEPL/xoTANBgkqhkiG9w0BAQUFADB2MQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MSAwHgYDVQQDExdDQyBTaWduZXQgLSBQ -Q0EgS2xhc2EgMjAeFw0wMjA0MTkxMDI5NTNaFw0xNzA0MTgxMjUzMDdaMHUxCzAJ -BgNVBAYTAlBMMR8wHQYDVQQKExZUUCBJbnRlcm5ldCBTcC4geiBvLm8uMSQwIgYD -VQQLExtDZW50cnVtIENlcnR5ZmlrYWNqaSBTaWduZXQxHzAdBgNVBAMTFkNDIFNp -Z25ldCAtIENBIEtsYXNhIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCqgLJuQqY4yavbSgHg8CyfKTx4BokNSDOVz4eD9vptUr11Kqd06ED1hlH7Sg0g -oBFAfntNU/QTKwSBaNuime7C4sSEdgsKrPoAhGb4Mq8y7Ty7RqZz7mkzNMqzL2L2 -U4yQ2QjvpH8MH0IBqOWEcpSkpwnrCDImRoTfd+YlZWKi2JceQixUUYIQ45Ox8+x8 -hHbvvZdgqtcvo8PW27qoHkp/7hMuJ44kDAGrmxffBXl/OBRZp0uO1CSLcMcVJzyr -2phKhy406MYdWrtNPEluGs0GFDzd0nrIctiWAO4cmct4S72S9Q6e//0GO9f3/Ca5 -Kb2I1xYLj/xE+HgjHX9aD2MhAgMBAAGjggGMMIIBiDAPBgNVHRMBAf8EBTADAQH/ -MA4GA1UdDwEB/wQEAwIBBjCB4wYDVR0gBIHbMIHYMIHVBg0rBgEEAb4/AhQKAQEA -MIHDMHUGCCsGAQUFBwICMGkaZ0NlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmll -IHogZG9rdW1lbnRlbTogIlBvbGl0eWthIENlcnR5ZmlrYWNqaSBQQ0EyIC0gQ2Vy -dHlmaWthdHkgVXJ6ZWRvdyBLbGFzeSAyIi4wSgYIKwYBBQUHAgEWPmh0dHA6Ly93 -d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9kb2t1bWVudHkva2xhc2EyL3BjX3Bj -YTIudHh0MD8GA1UdHwQ4MDYwNKAyoDCGLmh0dHA6Ly93d3cuc2lnbmV0LnBsL3Jl -cG96eXRvcml1bS9jcmwvcGNhMi5jcmwwHwYDVR0jBBgwFoAUwGxGyl2CfpYHRonE -82AVXO08kMIwHQYDVR0OBBYEFLtFBlILy4HNKVSzvHxBTM0HDowlMA0GCSqGSIb3 -DQEBBQUAA4IBAQBWTsCbqXrXhBBev5v5cIuc6gJM8ww7oR0uMQRZoFSqvQUPWBYM -2/TLI/f8UM9hSShUVj3zEsSj/vFHagUVmzuVXo5u0WK8iaqATSyEVBhADHrPG6wY -cLKJlagge/ILA0m+SieyP2sjYD9MUB9KZIEyBKv0429UuDTw6P7pslxMWJBSNyQx -aLIs0SRKsqZZWkc7ZYAj2apSkBMX2Is1oHA+PwkF6jQMwCao/+CndXPUzfCF6caa -9WwW31W26MlXCvSmJgfiTPwGvm4PkPmOnmWZ3CczzhHl4q7ztHFzshJH3sZWDnrW -wBFjzz5ePr3WHV1wA7EY6oT4zBx+2gT9XBTB +MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM +MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD +QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM +MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD +QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E +jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo +ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI +ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu +Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg +AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7 +HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA +uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa +TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg +xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q +CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x +O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs +6GAqm4VKQPNriiTsBhYscw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEejCCA2KgAwIBAgIEP4vk6TANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQgLSBD -QSBLbGFzYSAyMB4XDTAzMTAxNDExNTgyMloXDTE3MDQxODEyNTMwN1owdzELMAkG -A1UEBhMCUEwxHzAdBgNVBAoTFlRQIEludGVybmV0IFNwLiB6IG8uby4xJDAiBgNV -BAsTG0NlbnRydW0gQ2VydHlmaWthY2ppIFNpZ25ldDEhMB8GA1UEAxMYQ0MgU2ln -bmV0IC0gT0NTUCBLbGFzYSAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCo -VCsaBStblXQYVNthe3dvaCrfvKpPXngh4almm988iIlEv9CVTaAdCfaJNihvA+Vs -Qw8++ix1VqteMQE474/MV/YaXigP0Zr0QB+g+/7PWVlv+5U9Gzp9+Xx4DJay8AoI -iB7Iy5Qf9iZiHm5BiPRIuUXT4ZRbZRYPh0/76vgRsQIDAQABo4IBkjCCAY4wDgYD -VR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMJMEEGA1UdHwQ6MDgwNqA0 -oDKGMGh0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9jcmwva2xhc2Ey -LmNybDCB2AYDVR0gBIHQMIHNMIHKBg4rBgEEAb4/AoFICgwBADCBtzBsBggrBgEF -BQcCAjBgGl5DZXJ0eWZpa2F0IHd5ZGFueSB6Z29kbmllIHogZG9rdW1lbnRlbSAi -UG9saXR5a2EgQ2VydHlmaWthY2ppIC0gQ2VydHlmaWthdHkgcmVzcG9uZGVyb3cg -T0NTUCIuMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnNpZ25ldC5wbC9yZXBvenl0 -b3JpdW0vZG9rdW1lbnR5L3BjX29jc3BfMV8wLnBkZjAfBgNVHSMEGDAWgBS7RQZS -C8uBzSlUs7x8QUzNBw6MJTAdBgNVHQ4EFgQUKEVrOY7cEHvsVgvoyZdytlbtgwEw -CQYDVR0TBAIwADANBgkqhkiG9w0BAQUFAAOCAQEAQrRg5MV6dxr0HU2IsLInxhvt -iUVmSFkIUsBCjzLoewOXA16d2oDyHhI/eE+VgAsp+2ANjZu4xRteHIHoYMsN218M -eD2MLRsYS0U9xxAFK9gDj/KscPbrrdoqLvtPSMhUb4adJS9HLhvUe6BicvBf3A71 -iCNe431axGNDWKnpuj2KUpj4CFHYsWCXky847YtTXDjri9NIwJJauazsrSjK+oXp -ngRS506mdQ7vWrtApkh8zhhWp7duCkjcCo1O8JxqYr2qEW1fXmgOISe010v2mmuv -hHxPyVwoAU4KkOw0nbXZn53yak0is5+XmAjh0wWue44AssHrjC9nUh3mkLt6eQ== +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIFGjCCBAKgAwIBAgIEPL7eEDANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBS -b290Q0EwHhcNMDIwNDE4MTQ1NDA4WhcNMjYwOTIxMTU0MjE5WjB2MQswCQYDVQQG -EwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMb -Q2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MSAwHgYDVQQDExdDQyBTaWduZXQg -LSBQQ0EgS2xhc2EgMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM7B -rBlbN5maM5eg0BOTqoZ+9NBDvU8Lm5rTdrMswFTCathzpVVLK/JD4K3+4oCZ9SRA -spEXE4gvwb08ASY6w5s+HpRkeJw8YzMFR5kDZD5adgnCAy4vDfIXYZgppXPaTQ8w -nfUZ7BZ7Zfa7QBemUIcJIzJBB0UqgtxWCeol9IekpBRVmuuSA6QG0Jkm+pGDJ05y -j2eQG8jTcBENM7sVA8rGRMyFA4skSZ+D0OG6FS2xC1i9JyN0ag1yII/LPx8HK5J4 -W9MaPRNjAEeaa2qI9EpchwrOxnyVbQfSedCG1VRJfAsE/9tT9CMUPZ3xW20QjQcS -ZJqVcmGW9gVsXKQOVLsCAwEAAaOCAbMwggGvMA8GA1UdEwEB/wQFMAMBAf8wDgYD -VR0PAQH/BAQDAgEGMIIBBAYDVR0gBIH8MIH5MIH2Bg0rBgEEAb4/AgEKAQEBMIHk -MIGaBggrBgEFBQcCAjCBjRqBikNlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmll -IHogZG9rdW1lbnRlbTogIlBvbGl0eWthIENlcnR5ZmlrYWNqaSBkbGEgUm9vdENB -Ii4gQ2VydHlmaWthdCB3eXN0YXdpb255IHByemV6IFJvb3RDQSB3IGhpZXJhcmNo -aWkgQ0MgU2lnbmV0LjBFBggrBgEFBQcCARY5aHR0cDovL3d3dy5zaWduZXQucGwv -cmVwb3p5dG9yaXVtL2Rva3VtZW50eS9wY19yb290Y2EudHh0MEQGA1UdHwQ9MDsw -OaA3oDWGM2h0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9yb290Y2Ev -cm9vdGNhLmNybDAfBgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAdBgNV -HQ4EFgQUwGxGyl2CfpYHRonE82AVXO08kMIwDQYJKoZIhvcNAQEFBQADggEBABp1 -TAUsa+BeVWg4cjowc8yTJ5XN3GvN96GObMkxUGY7U9kVrLI71xBgoNVyzXTiMNDB -vjh7vdPWjpl5SDiRpnnKiOFXA43HvNWzUaOkTu1mxjJsZsanot1Xt6j0ZDC+03Fj -LHdYMyM9kSWp6afb4980EPYZCcSzgM5TOGfJmNii5Tq468VFKrX+52Aou1G22Ohu -+EEOlOrG7ylKv1hHUJJCjwN0ZVEIn1nDbrU9FeGCz8J9ihVUvnENEBbBkU37PWqW -uHitKQDVtcwTwJJdR8cmKq3NmkwAm9fPacidQLpaw0WkuGrS+fEDhu1Nhy9xELP6 -NA9GRTCNxm/dXlcwnmY= +MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhV +MRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMe +TmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0 +dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBB +KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0 +N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhC +dWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQu +MRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBL +b3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiD +zl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi +3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8 +WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LY +Oph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2Esi +NCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCC +ApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4 +QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0 +YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz +aSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu +IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtm +ZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMg +ZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVs +amFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVndGFsYWxoYXRv +IGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8vd3d3 +Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6 +ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1 +YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg +dG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRs +b2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0G +CSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQO +xmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP +0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQ +QeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxk +f1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK +8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK +VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm +Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J +h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul +uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68 +DzFc6PLZ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFGjCCBAKgAwIBAgIEPV0tNDANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQ @@ -2025,81 +1405,6 @@ OcePEhKz1Ag52y6Wf0nJJB9yk0sFakqZH18F7eQecQImgZyyeRtsG95leNugB3BX WCW+KxwiBrtQTXv4dTE= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEzzCCA7egAwIBAgIEO6ocGTANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBS -b290Q0EwHhcNMDEwOTIwMTY0MjE5WhcNMjYwOTIxMTU0MjE5WjBxMQswCQYDVQQG -EwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMb -Q2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQg -LSBSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrr2vydnNp -ELfGW3KsARiDhJvwDtUe4AbWev+OfMc3+vA29nX8ZmIwno3gmItjo5DbUCCRiCMq -5c9epcGu+kg4a3BJChVXREl8gVh0ST15rr3RKrSc4VgsvQzl0ZUraeQLl8JoRT5P -LsUj3qwF78jUCQVckiiLVcnGfZtFCm+DCJXliQBDMB9XFAUEiO/DtEBs0B7wJGx7 -lgJeJpQUcGiaOPjcJDYOk7rNAYmmD2gWeSlepufO8luUYG/YDxTC4mqhRqfa4MnV -O5dqy+ICj2UvUpHbZDB0KfGRibgBYeQP1kuqgIzJN4UqknVAJb0aMBSPl+9k2fAU -dchx1njlbdcbAgMBAAGjggFtMIIBaTAPBgNVHRMBAf8EBTADAQH/MIIBBAYDVR0g -BIH8MIH5MIH2Bg0rBgEEAb4/AgEKAQEAMIHkMIGaBggrBgEFBQcCAjCBjRqBikNl -cnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmllIHogZG9rdW1lbnRlbTogIlBvbGl0 -eWthIENlcnR5ZmlrYWNqaSBkbGEgUm9vdENBIi4gQ2VydHlmaWthdCB3eXN0YXdp -b255IHByemV6IFJvb3RDQSB3IGhpZXJhcmNoaWkgQ0MgU2lnbmV0LjBFBggrBgEF -BQcCARY5aHR0cDovL3d3dy5zaWduZXQucGwvcmVwb3p5dG9yaXVtL2Rva3VtZW50 -eS9wY19yb290Y2EudHh0MB0GA1UdDgQWBBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAf -BgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAOBgNVHQ8BAf8EBAMCAQYw -DQYJKoZIhvcNAQEFBQADggEBAGnY5QmYqnnO9OqFOWZxxb25UHRnaRF6IV9aaGit -5BZufZj2Tq3v8L3SgE34GOoIcdRMMG5JEpEU4mN/Ef3oY6Eo+7HfqaPHI4KFmbDS -PiK5s+wmf+bQSm0Yq5/h4ZOdcAESlLQeLSt1CQk2JoKQJ6pyAf6xJBgWEIlm4RXE -4J3324PUiOp83kW6MDvaa1xY976WyInr4rwoLgxVl11LZeKWha0RJJxJgw/NyWpK -G7LWCm1fglF8JH51vZNndGYq1iKtfnrIOvLZq6bzaCiZm1EurD8HE6P7pmABKK6o -3C2OXlNfNIgwkDN/cDqk5TYsTkrpfriJPdxXBH8hQOkW89g= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID/TCCA2agAwIBAgIEP4/gkTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJQ -TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu -dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQgLSBD -QSBLbGFzYSAxMB4XDTAzMTAxNzEyMjkwMloXDTExMDkyMzExMTgxN1owdjELMAkG -A1UEBhMCUEwxHzAdBgNVBAoTFlRQIEludGVybmV0IFNwLiB6IG8uby4xJDAiBgNV -BAsTG0NlbnRydW0gQ2VydHlmaWthY2ppIFNpZ25ldDEgMB4GA1UEAxMXQ0MgU2ln -bmV0IC0gVFNBIEtsYXNhIDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOJY -rISEtSsduHajROh5/n7NGrkpYTT9NEaPe9+ucuQ37KxIbfJwXJjgUc1dw4wCkcQ1 -2FJarD1X6mSQ4cfN/60vLfKI5ZD4nhJTMKlAj1pX9ScQ/MuyvKStCbn5WTkjPhjR -AM0tdwXSnzuTEunfw0Oup559y3Iqxg1cExflB6cfAgMBAAGjggGXMIIBkzBBBgNV -HR8EOjA4MDagNKAyhjBodHRwOi8vd3d3LnNpZ25ldC5wbC9yZXBvenl0b3JpdW0v -Y3JsL2tsYXNhMS5jcmwwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsG -AQUFBwMIMIHaBgNVHSAEgdIwgc8wgcwGDSsGAQQBvj8CZAoRAgEwgbowbwYIKwYB -BQUHAgIwYxphQ2VydHlmaWthdCB3eXN0YXdpb255IHpnb2RuaWUgeiBkb2t1bWVu -dGVtICJQb2xpdHlrYSBDZXJ0eWZpa2FjamkgQ0MgU2lnbmV0IC0gWm5ha293YW5p -ZSBjemFzZW0iLjBHBggrBgEFBQcCARY7aHR0cDovL3d3dy5zaWduZXQucGwvcmVw -b3p5dG9yaXVtL2Rva3VtZW50eS9wY190c2ExXzJfMS5wZGYwHwYDVR0jBBgwFoAU -w4Me1Vl3VPtN+1dH+cQjXNHnieMwHQYDVR0OBBYEFJdDwEqtcavOYd9u9tej53vW -XwNBMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADgYEAnpiQkqLCJQYXUrqMHUEz -+z3rOqS0XzSFnVVLhkVssvXc8S3FkJIiQTUrkScjI4CToCzujj3EyfNxH6yiLlMb -skF8I31JxIeBvueqV+s+o76CZm3ycu9hb0I4lswuxoT+q5ZzPR8Irrb51rZXlolR -+7KtwMg4sFDJZ8RNgOf7tbA= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDvjCCA3ygAwIBAgIFJQaThoEwCwYHKoZIzjgEAwUAMIGFMQswCQYDVQQGEwJG -UjEPMA0GA1UECBMGRnJhbmNlMQ4wDAYDVQQHEwVQYXJpczEQMA4GA1UEChMHUE0v -U0dETjEOMAwGA1UECxMFRENTU0kxDjAMBgNVBAMTBUlHQy9BMSMwIQYJKoZIhvcN -AQkBFhRpZ2NhQHNnZG4ucG0uZ291di5mcjAeFw0wMjEyMTMxNDM5MTVaFw0yMDEw -MTcxNDM5MTRaMIGFMQswCQYDVQQGEwJGUjEPMA0GA1UECBMGRnJhbmNlMQ4wDAYD -VQQHEwVQYXJpczEQMA4GA1UEChMHUE0vU0dETjEOMAwGA1UECxMFRENTU0kxDjAM -BgNVBAMTBUlHQy9BMSMwIQYJKoZIhvcNAQkBFhRpZ2NhQHNnZG4ucG0uZ291di5m -cjCCAbYwggErBgcqhkjOOAQBMIIBHgKBgQCFkMImdk9zDzJfTO4XPdAAmLbAdWws -ZiEMZh19RyTo3CyhFqO77OIXrwY6vc1pcc3MgWJ0dgQpAgrDMtmFFxpUu4gmjVsx -8GpxQC+4VOgLY8Cvmcd/UDzYg07EIRto8BwCpPJ/JfUxwzV2V3N713aAX+cEoKZ/ -s+kgxC6nZCA7oQIVALME/JYjkdW2uKIGngsEPbXAjdhDAoGADh/uqWJx94UBm31c -9d8ZTBfRGRnmSSRVFDgPWgA69JD4BR5da8tKz+1HjfMhDXljbMH86ixpD5Ka1Z0V -pRYUPbyAoB37tsmXMJY7kjyD19d5VdaZboUjVvhH6UJy5lpNNNGSvFl4fqkxyvw+ -pq1QV0N5RcvK120hlXdfHUX+YKYDgYQAAoGAQGr7IuKJcYIvJRMjxwl43KxXY2xC -aoCiM/bv117MfI94aNf1UusGhp7CbYAY9CXuL60P0oPMAajbaTE5Z34AuITeHq3Y -CNMHwxalip8BHqSSGmGiQsXeK7T+r1rPXsccZ1c5ikGDZ4xn5gUaCyy2rCmb+fOJ -6VAfCbAbAjmNKwejdzB1MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgFGMBUG -A1UdIAQOMAwwCgYIKoF6AXkBAQEwHQYDVR0OBBYEFPkeNRcUf8idzpKblYbLNxs0 -MQhSMB8GA1UdIwQYMBaAFPkeNRcUf8idzpKblYbLNxs0MQhSMAsGByqGSM44BAMF -AAMvADAsAhRVh+CJA5eVyEYU5AO9Tm7GxX0rmQIUBCqsU5u1WxoZ5lEXicDX5/Ob -sRQ= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYT AkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQ TS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG @@ -2124,397 +1429,272 @@ NjSaTFR+FwNIlQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R 0982gaEbeC9xs/FZTEYYKKuF0mBWWg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB -gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV -BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw -MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl -YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P -RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 -UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI -2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 -Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp -+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ -DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O -nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW -/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g -PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u -QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY -SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv -IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ -RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 -zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd -BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB -ZQ== +MIIH/zCCB2igAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARwxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEzMDEGA1UECxMq +SVBTIENBIENoYWluZWQgQ0FzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTMwMQYD +VQQDEypJUFMgQ0EgQ2hhaW5lZCBDQXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx +HjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczAeFw0wMTEyMzExMTE0NTRa +Fw0yNTEyMjkxMTE0NTRaMIIBHDELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNl +bG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQg +cHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMu +ZXMgQy5JLkYuICBCLTYwOTI5NDUyMTMwMQYDVQQLEypJUFMgQ0EgQ2hhaW5lZCBD +QXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMzAxBgNVBAMTKklQUyBDQSBDaGFp +bmVkIENBcyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3DQEJARYP +aXBzQG1haWwuaXBzLmVzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpOZZJ +iHAzKHzoV9xIki3eLXp56UjxFehnY+c+Dh1nUiVO0t//vmGMP6B2LTFfx9FBKRBi +kYcW7raIcSDi62Or0sAG5UUgG4ruGLE7XtCnnx4xjgbFZ4tTjdgi5Wh9GVhfP7Oo +9ahi8Eqao+alFbhvB6LD3xZZqM2j9cmD8GzYAQIDAQABo4IESzCCBEcwHQYDVR0O +BBYEFAeUqHBsCqTumbhV3S5MRXf2Nq+5MIIBTgYDVR0jBIIBRTCCAUGAFAeUqHBs +CqTumbhV3S5MRXf2Nq+5oYIBJKSCASAwggEcMQswCQYDVQQGEwJFUzESMBAGA1UE +CBMJQmFyY2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJ +bnRlcm5ldCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0Bt +YWlsLmlwcy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxMzAxBgNVBAsTKklQUyBDQSBD +aGFpbmVkIENBcyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEzMDEGA1UEAxMqSVBT +IENBIENoYWluZWQgQ0FzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI +hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8E +BQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMG +CCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYB +BAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMw +EYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlwcy5lczBD +BglghkgBhvhCAQ0ENhY0Q2hhaW5lZCBDQSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkg +aHR0cHM6Ly93d3cuaXBzLmVzLzAqBglghkgBhvhCAQIEHRYbaHR0cHM6Ly93d3cu +aXBzLmVzL2lwczIwMDIvMDgGCWCGSAGG+EIBBAQrFilodHRwczovL3d3dy5pcHMu +ZXMvaXBzMjAwMi9pcHMyMDAyQ0FDLmNybDA9BglghkgBhvhCAQMEMBYuaHR0cHM6 +Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2b2NhdGlvbkNBQy5odG1sPzA6BglghkgB +hvhCAQcELRYraHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmVuZXdhbENBQy5o +dG1sPzA4BglghkgBhvhCAQgEKxYpaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIv +cG9saWN5Q0FDLmh0bWwwbwYDVR0fBGgwZjAvoC2gK4YpaHR0cHM6Ly93d3cuaXBz +LmVzL2lwczIwMDIvaXBzMjAwMkNBQy5jcmwwM6AxoC+GLWh0dHBzOi8vd3d3YmFj +ay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0FDLmNybDAvBggrBgEFBQcBAQQjMCEw +HwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQAD +gYEATiRvY2nro9B6QNgTOgojWSrXMKpXHa6hLRxL2GZPEFg059x2ERs3pw7RlJJZ +ctupZam06zvBnGfQL4ZhevXl6ST6RAAmOikuj8kbiFSgujjCJY1wv5/7zzgBWzdL +NzqKC18p1T2KZa8B2qKfQCqzV/J3fgI/725+9ekqKNLiE5Q= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn -MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL -ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg -b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa -MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB -ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw -IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B -AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb -unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d -BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq -7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 -0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX -roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG -A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j -aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p -26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA -BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud -EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN -BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz -aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB -AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd -p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi -1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc -XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 -eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu -tGWaIZDgqtCYvDi1czyL+Nw= +MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc +MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj +IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB +IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE +RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl +U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 +IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU +ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC +QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr +rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S +NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc +QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH +txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP +BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC +AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp +tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa +IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl +6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ +xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU +Cm26OWMohpLzGITY+9HPBVZkVw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn -MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL -ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo -YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 -MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy -NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G -A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA -A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 -Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s -QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV -eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 -B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh -z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T -AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i -ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w -TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH -MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD -VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE -VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh -bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B -AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM -bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi -ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG -VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c -ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ -AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +MIIFaDCCBFCgAwIBAgIQO1nHe81bV569N1KsdrSqGjANBgkqhkiG9w0BAQUFADBi +MRIwEAYDVQQKEwliZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENB +czEvMC0GA1UEAxMmYmVUUlVTVGVkIFJvb3QgQ0EgLSBSU0EgSW1wbGVtZW50YXRp +b24wHhcNMDIwNDExMTExODEzWhcNMjIwNDEyMTEwNzI1WjBiMRIwEAYDVQQKEwli +ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEvMC0GA1UEAxMm +YmVUUlVTVGVkIFJvb3QgQ0EgLSBSU0EgSW1wbGVtZW50YXRpb24wggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkujQwCY5X0LkGLG9uJIAiv11DpvpPrILn +HGhwhRujbrWqeNluB0s/6d/16uhUoWGKDi9pdRi3DOUUjXFumLhV/AyV0Jtu4S2I +1DpAa5LxmZZk3tv/ePTulh1HiXzUvrmIdyM6CeYEnm2qXtLIvZpOGd+J6lsOfsPk +tPDgaTuID0GQ+NRxQyTBjyZLO1bp/4xsN+lFrYWMU8NghpBKlsmzVLC7F/AcRdnU +GxlkVgoZ98zh/4avflherHqQH8koOUV7orbHnB/ahdQhhlkwk75TMzf270HPM8er +cmsl9fNTGwxMLvF1S++gh/f+ihXQbNXL+WhTuXAVE8L1LvtDNXUtAgMBAAGjggIY +MIICFDAMBgNVHRMEBTADAQH/MIIBtQYDVR0gBIIBrDCCAagwggGkBg8rBgEEAbE+ +AAADCSiDkTEwggGPMEEGCCsGAQUFBwIBFjVodHRwOi8vd3d3LmJldHJ1c3RlZC5j +b20vcHJvZHVjdHNfc2VydmljZXMvaW5kZXguaHRtbDCCAUgGCCsGAQUFBwICMIIB +OhqCATZSZWxpYW5jZSBvbiBvciB1c2Ugb2YgdGhpcyBDZXJ0aWZpY2F0ZSBjcmVh +dGVzIGFuIGFja25vd2xlZGdtZW50IGFuZCBhY2NlcHRhbmNlIG9mIHRoZSB0aGVu +IGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdXNl +LCB0aGUgQ2VydGlmaWNhdGlvbiBQcmFjdGljZSBTdGF0ZW1lbnQgYW5kIHRoZSBS +ZWx5aW5nIFBhcnR5IEFncmVlbWVudCwgd2hpY2ggY2FuIGJlIGZvdW5kIGF0IHRo +ZSBiZVRSVVNUZWQgd2ViIHNpdGUsIGh0dHA6Ly93d3cuYmV0cnVzdGVkLmNvbS9w +cm9kdWN0c19zZXJ2aWNlcy9pbmRleC5odG1sMAsGA1UdDwQEAwIBBjAfBgNVHSME +GDAWgBSp7BR++dlDzFMrFK3P9/BZiUHNGTAdBgNVHQ4EFgQUqewUfvnZQ8xTKxSt +z/fwWYlBzRkwDQYJKoZIhvcNAQEFBQADggEBANuXsHXqDMTBmMpWBcCorSZIry0g +6IHHtt9DwSwddUvUQo3neqh03GZCWYez9Wlt2ames30cMcH1VOJZJEnl7r05pmuK +mET7m9cqg5c0Lcd9NUwtNLg+DcTsiCevnpL9UGGCqGAHFFPMZRPB9kdEadIxyKbd +LrML3kqNWz2rDcI1UqJWN8wyiyiFQpyRQHpwKzg21eFzGh/l+n5f3NacOzDq28Bb +J1zTcwfBwvNMm2+fG8oeqqg4MwlYsq78B+g23FW6L09A/nq9BqaBwZMifIYRCgZ3 +SK41ty8ymmFei74pnykkiFY5LKjSq5YDWtRIn7lAhAuYaPsBQ9Yb4gmxlxw= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw -PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz -cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 -MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz -IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ -ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR -VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL -kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd -EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas -H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 -HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud -DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 -QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu -Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ -AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 -yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR -FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA -ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB -kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 -l7+ijrRU +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 +MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE +ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j +b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg +U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ +I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 +wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC +AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb +oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 +BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p +dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk +MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 +MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi +E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa +MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI +hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN +95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd +2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBb -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qx -ETAPBgNVBAsTCERTVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0w -MzExMjAyMTE5NThaFw0xNzExMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYD -VQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UECxMIRFNUIEFDRVMx -FzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPu -ktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7 -gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH -fAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4a -ahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEIT -ajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQF -MAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rk -c3QuY29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjto -dHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMt -aW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZI -hvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99Pe7lv7Uk -QIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/ -h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq -nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpR -rscL9yuwNwXsvFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf2 -9w4LTJxoeHtxMcfrHuBnQfO3oKfN5XozNmr6mis= +MIIEUzCCAzugAwIBAgIDAOJDMA0GCSqGSIb3DQEBBQUAMIHPMQswCQYDVQQGEwJB +VDGBizCBiAYDVQQKHoGAAEEALQBUAHIAdQBzAHQAIABHAGUAcwAuACAAZgD8AHIA +IABTAGkAYwBoAGUAcgBoAGUAaQB0AHMAcwB5AHMAdABlAG0AZQAgAGkAbQAgAGUA +bABlAGsAdAByAC4AIABEAGEAdABlAG4AdgBlAHIAawBlAGgAcgAgAEcAbQBiAEgx +GDAWBgNVBAsTD0EtVHJ1c3QtUXVhbC0wMTEYMBYGA1UEAxMPQS1UcnVzdC1RdWFs +LTAxMB4XDTA0MTEzMDIzMDAwMFoXDTE0MTEzMDIzMDAwMFowgc8xCzAJBgNVBAYT +AkFUMYGLMIGIBgNVBAoegYAAQQAtAFQAcgB1AHMAdAAgAEcAZQBzAC4AIABmAPwA +cgAgAFMAaQBjAGgAZQByAGgAZQBpAHQAcwBzAHkAcwB0AGUAbQBlACAAaQBtACAA +ZQBsAGUAawB0AHIALgAgAEQAYQB0AGUAbgB2AGUAcgBrAGUAaAByACAARwBtAGIA +SDEYMBYGA1UECxMPQS1UcnVzdC1RdWFsLTAxMRgwFgYDVQQDEw9BLVRydXN0LVF1 +YWwtMDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmhgdxIbxTGEOH +fXGiewI3NFldAWKFWfLofO+5I1UbvA5avt7IgsGXz/tI/f5HGUbascI0i7xG0tqV +lA5ctQgLRqxgxHtgTkMcqsAEYdsz3LZsCdXO1QrvEBGLTSABdxiL/gSWJ6z77CSw +x7Xg02HwxPV82cjGkSF3ENGJntuIAAnRDWn/ORHjFatNRymoMbHaOEZXSGhf7Y5F +rrHEqGyi9E6sv784De/T1aTvskn8cWeUmDzv//omiG/a/V9KQex/61XN8OthUQVn +X+u/liL2NKx74I2C/GgHX5B0WkPNqsSOgmlvJ/cKuT0PveUgVFDAA0oYBgcE1KDM +lBbN0kmPAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECEs8jB2F +6W+tMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAIUusmJzMJRiQ +8TAHrJAOelfuWoTGcqdIv7Tys/fNl2yF2fjvHT8J01aKialFVpbVeQ2XKb1O2bHO +QYAKgsdZ2jZ/sdL2UVFRTHmidLu6PdgWCBRhJYQELQophO9QVvfhAA0TwbESYqTz ++nlI5Gr7CZe8f6HEmhJmCtUQsdQCufGglRh4T+tIGiNGcnyVEHZ93mSVepFr1VA2 +9CTRPteuGjA81jeAz9peYiFE1CXvxK9cJiv0BcALFLWmADCoRLzIRZhA+sAwYUmw +M1rqVCPA3kBQvIC95tyQvNy2dG0Vs+O6PwLaNX/suSlElQ06X2l1VwMaYb4vZKFq +N0bOhBXEVg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ -MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT -DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O -rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq -OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b -xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw -7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD -aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG -SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 -ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr -AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz -R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 -JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo -Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC +VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ +cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ +BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt +VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D +0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 +ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G +A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs +aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I +flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c -JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP -mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ -wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 -VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ -AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB -AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun -pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC -dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf -fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm -NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx -H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln +biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF +MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT +d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 +76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ +bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c +6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE +emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd +MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt +MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y +MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y +FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi +aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM +gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB +qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 +lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn +8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 +45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO +UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 +O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC +bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv +GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a +77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC +hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 +92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp +Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w +ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt +Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX +DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy +dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj +YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV +OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr +zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM +VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ +hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO +ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw +awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs +OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF +coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc +okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 +t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy +1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ +SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm -+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW -PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM -xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB -Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 -hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg -EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA -FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec -nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z -eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF -hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 -Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep -+OkuE6N36B9K +MIIDyzCCArOgAwIBAgIDAOJIMA0GCSqGSIb3DQEBBQUAMIGLMQswCQYDVQQGEwJB +VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp +bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRgwFgYDVQQLDA9BLVRydXN0LVF1 +YWwtMDIxGDAWBgNVBAMMD0EtVHJ1c3QtUXVhbC0wMjAeFw0wNDEyMDIyMzAwMDBa +Fw0xNDEyMDIyMzAwMDBaMIGLMQswCQYDVQQGEwJBVDFIMEYGA1UECgw/QS1UcnVz +dCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy +a2VociBHbWJIMRgwFgYDVQQLDA9BLVRydXN0LVF1YWwtMDIxGDAWBgNVBAMMD0Et +VHJ1c3QtUXVhbC0wMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJaR +q9eOsFm4Ab20Hq2Z/aH86gyWa48uSUjY6eQkguHYuszr3gdcSMYZggFHQgnhfLmf +ro/27l5rqKhWiDhWs+b+yZ1PNDhRPJy+86ycHMg9XJqErveULBSyZDdgjhSwOyrN +ibUir/fkf+4sKzP5jjytTKJXD/uCxY4fAd9TjMEVpN3umpIS0ijpYhclYDHvzzGU +833z5Dwhq5D8bc9jp8YSAHFJ1xzIoO1jmn3jjyjdYPnY5harJtHQL73nDQnfbtTs +5ThT9GQLulrMgLU4WeyAWWWEMWpfVZFMJOUkmoOEer6A8e5fIAeqdxdsC+JVqpZ4 +CAKel/Arrlj1gFA//jsCAwEAAaM2MDQwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4E +CgQIQj0rJKbBRc4wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBG +yxFjUA2bPkXUSC2SfJ29tmrbiLKal+g6a9M8Xwd+Ejo+oYkNP6F4GfeDtAXpm7xb +9Ly8lhdbHcpRhzCUQHJ1tBCiGdLgmhSx7TXjhhanKOdDgkdsC1T+++piuuYL72TD +gUy2Sb1GHlJ1Nc6rvB4fpxSDAOHqGpUq9LWsc3tFkXqRqmQVtqtR77npKIFBioc6 +2jTBwDMPX3hDJDR1DSPc6BnZliaNw2IHdiMQ0mBoYeRnFdq+TyDKsjmJOOQPLzzL +/saaw6F891+gBjLFEFquDyR73lAPJS279R3csi8WWk4ZYUC/1V8H3Ktip/J6ac8e +qhLCbmJ81Lo92JGHz/ot -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 -Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW -KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw -NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw -NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy -ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV -BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo -Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 -4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 -KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI -rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi -94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB -sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi -gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo -kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE -vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t -O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua -AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP -9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ -eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m -0vdXcDazv/wor3ElhVsT/h5/WrQ8 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMx -IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1 -dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 -MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w -HhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTELMAkGA1UEBhMCRVMx -IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1 -dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 -MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5u -Cp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5Vj1H5WuretXDE7aTt/6MNbg9kUDGvASdY -rv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJHlShbz++AbOCQl4oBPB3z -hxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf3H5idPay -BQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcL -iam8NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcb -AgMBAAGjgZ8wgZwwKgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lv -bmFsLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0 -MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E -FgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQADggEBAEdz/o0n -VPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq -u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36m -hoEyIwOdyPdfwUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzfl -ZKG+TQyTmAyX9odtsz/ny4Cm7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBp -QWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YGVM+h4k0460tQtcsm9MracEpqoeJ5 -quGnM/b9Sh/22WA= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs -IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg -R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A -PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8 -Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL -TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL -5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7 -S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe -2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE -FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap -EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td -EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv -/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN -A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0 -abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF -I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz -4iIprn2DQKi6bA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY -MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo -R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx -MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK -Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 -AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA -ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 -7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W -kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI -mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ -KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 -6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl -4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K -oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj -UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU -AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy -c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE -BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 -IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV -VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 -cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT -QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh -F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v -c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w -mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd -VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX -teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ -f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe -Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ -nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB -/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY -MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG -9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc -aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX -IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn -ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z -uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN -Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja -QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW -koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 -ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt -DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm -bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy -c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD -VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 -c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 -WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG -FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq -XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL -se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb -KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd -IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 -y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt -hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc -QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 -Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV -HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ -KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z -dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ -L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr -Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo -ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY -T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz -GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m -1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV -OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH -6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX -QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 -MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL -v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 -eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq -tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd -C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa -zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB -mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH -V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n -bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG -3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs -J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO -291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS -ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd -AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +MIIEXzCCA0egAwIBAgIBATANBgkqhkiG9w0BAQUFADCB0DELMAkGA1UEBhMCRVMx +SDBGBgNVBAoTP0laRU5QRSBTLkEuIC0gQ0lGIEEtMDEzMzcyNjAtUk1lcmMuVml0 +b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFCMEAGA1UEBxM5QXZkYSBkZWwgTWVk +aXRlcnJhbmVvIEV0b3JiaWRlYSAzIC0gMDEwMTAgVml0b3JpYS1HYXN0ZWl6MRMw +EQYDVQQDEwpJemVucGUuY29tMR4wHAYJKoZIhvcNAQkBFg9JbmZvQGl6ZW5wZS5j +b20wHhcNMDMwMTMwMjMwMDAwWhcNMTgwMTMwMjMwMDAwWjCB0DELMAkGA1UEBhMC +RVMxSDBGBgNVBAoTP0laRU5QRSBTLkEuIC0gQ0lGIEEtMDEzMzcyNjAtUk1lcmMu +Vml0b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFCMEAGA1UEBxM5QXZkYSBkZWwg +TWVkaXRlcnJhbmVvIEV0b3JiaWRlYSAzIC0gMDEwMTAgVml0b3JpYS1HYXN0ZWl6 +MRMwEQYDVQQDEwpJemVucGUuY29tMR4wHAYJKoZIhvcNAQkBFg9JbmZvQGl6ZW5w +ZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1btoCXXhp3xIW +D+Bxl8nUCxkyiazWfpt0e68t+Qt9+lZjKZSdEw2Omj4qvr+ovRmDXO3iWpWVOWDl +3JHJjAzFCe8ZEBNDH+QNYwZHmPBaMYFOYFdbAFVHWvys152C308hcFJ6xWWGmjvl +2eMiEl9P2nR2LWue368DCu+ak7j3gjAXaCOdP1a7Bfr+RW3X2SC5R4Xyp8iHlL5J +PHJD/WBkLrezwzQPdACw8m9EG7q9kUwlNpL32mROujS3ZkT6mQTzJieLiE3X04s0 +uIUqVkk5MhjcHFf7al0N5CzjtTcnXYJKN2Z9EDVskk4olAdGi46eSoZXbjUOP5gk +Ej6wVZAXAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG +MB0GA1UdDgQWBBTqVk/sPIOhFIh4gbIrBSLAB0FbQjANBgkqhkiG9w0BAQUFAAOC +AQEAYp7mEzzhw6o5Hf5+T5kcI+t4BJyiIWy7vHlLs/G8dLYXO81aN/Mzg928eMTR +TxxYZL8dd9uwsJ50TVfX6L0R4Dyw6wikh3fHRrat9ufXi63j5K91Ysr7aXqnF38d +iAgHYkrwC3kuxHBb9C0KBz6h8Q45/KCyN7d37wWAq38yyhPDlaOvyoE6bdUuK5hT +m5EYA5JmPyrhQ1moDOyueWBAjxzMEMj+OAY1H90cLv6wszsqerxRrdTOHBdv7MjB +EIpvEEQkXUxVXAzFuuT6m2t91Lfnwfl/IvljHaVC7DlyyhRYHD6D4Rx+4QKp4tWL +vpw6LkI+gKNJ/YdMCsRZQzEEFA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh @@ -2572,72 +1752,1161 @@ n3BukxowOR0w2y7jfLKRstE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKS NitjrFgBazMpUIaD8QFI -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUx -ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 -b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQD -EytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4X -DTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJBgNVBAYTAkhVMREw -DwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9u -c2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMr -TmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA -OoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC -2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwW -RMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0P -AQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEW -ggJNRklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0 -YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFz -b2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBO -ZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2ZWRpLiBB -IGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs -b2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs -ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25s -YXBqYW4gYSBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kg -a2VyaGV0byBheiBlbGxlbm9yemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4g -SU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0 -aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQUyBhdmFpbGFibGUg -YXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwgYXQg -Y3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmY -ta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g -pO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4 -Fp1hBWeAyNDYpQcCNJgEjTME1A== +MIICZzCCAdCgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEcMBoGA1UEAxMTRG9EIENMQVNTIDMgUm9vdCBDQTAeFw0wMDA1MTkxMzEz +MDBaFw0yMDA1MTQxMzEzMDBaMGExCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMu +IEdvdmVybm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRwwGgYDVQQD +ExNEb0QgQ0xBU1MgMyBSb290IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQC1MP5kvurMbe2BLPd/6Rm6DmlqKOGpqcuVWB/x5pppU+CIP5HFUbljl6jmIYwT +XjY8qFf6+HAsTGrLvzCnTBbkMlz4ErBR+BZXjS+0TfouqJToKmHUVw1Hzm4sL36Y +Z8wACKu2lhY1woWR5VugCsdmUmLzYXWVF668KlYppeArUwIDAQABoy8wLTAdBgNV +HQ4EFgQUbJyl8FyPbUGNxBc7kFfCD6PNbf4wDAYDVR0TBAUwAwEB/zANBgkqhkiG +9w0BAQUFAAOBgQCvcUT5lyPMaGmMQwdBuoggsyIAQciYoFUczT9usZNcrfoYmrsc +c2/9JEKPh59Rz76Gn+nXikhPCNlplKw/5g8tlw8ok3ZPYt//oM1h+KaGDDE0INx/ +L6j7Ob6V7jhZAmLB3mwVT+DfnbvkeXMk/WNklfdKqJkfSGWVx3u/eDLneg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhV -MRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMe -TmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0 -dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBB -KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0 -N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhC -dWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQu -MRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBL -b3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiD -zl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi -3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8 -WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LY -Oph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2Esi -NCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCC -ApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4 -QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0 -YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz -aSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu -IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtm -ZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMg -ZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVs -amFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVndGFsYWxoYXRv -IGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8vd3d3 -Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6 -ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1 -YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg -dG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRs -b2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0G -CSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQO -xmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP -0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQ -QeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxk -f1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK -8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDNjCCAp+gAwIBAgIQNhIilsXjOKUgodJfTNcJVDANBgkqhkiG9w0BAQUFADCB +zjELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJ +Q2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UE +CxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhh +d3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNl +cnZlckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIxMDEwMTIzNTk1OVow +gc4xCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcT +CUNhcGUgVG93bjEdMBsGA1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNV +BAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRo +YXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1z +ZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2 +aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560 +ZXUCTe/LCaIhUdib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j ++ao6hnO2RlNYyIkFvYMRuHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBlkKyID1bZ5jA01CbH0FDxkt5r1DmI +CSLGpmODA/eZd9iy5Ri4XWPz1HP7bJyZePFLeH0ZJMMrAoT4vCLZiiLXoPxx7JGH +IPG47LHlVYCsPVLIOQ7C8MAFT9aCdYy9X9LcdpoFEsmvcsPcJX6kTY4XpeCHf+Ga +WuFg3GQjPEIuTQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICXDCCAcWgAwIBAgIQCgEBAQAAAnwAAAALAAAAAjANBgkqhkiG9w0BAQUFADA6 +MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp +dHkgMTAyNCBWMzAeFw0wMTAyMjIyMTAxNDlaFw0yNjAyMjIyMDAxNDlaMDoxGTAX +BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAx +MDI0IFYzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDV3f5mCc8kPD6ugU5O +isRpgFtZO9+5TUzKtS3DJy08rwBCbbwoppbPf9dYrIMKo1W1exeQFYRMiu4mmdxY +78c4pqqv0I5CyGLXq6yp+0p9v+r+Ek3d/yYtbzZUaMjShFbuklNhCbM/OZuoyZu9 +zp9+1BlqFikYvtc6adwlWzMaUQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBTEwBykB5T9zU0B1FTapQxf3q4FWjAd +BgNVHQ4EFgQUxMAcpAeU/c1NAdRU2qUMX96uBVowDQYJKoZIhvcNAQEFBQADgYEA +Py1q4yZDlX2Jl2X7deRyHUZXxGFraZ8SmyzVWujAovBDleMf6XbN3Ou8k6BlCsdN +T1+nr6JGFLkM88y9am63nd4lQtBU/55oc2PcJOsiv6hy8l4A4Q1OOkNumU4/iXgD +mMrzVcydro7BqkWY+o8aoI2II/EVQQ2lRj6RP4vr93E= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL +MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV +BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1 +c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx +MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg +R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD +VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR +JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T +fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu +jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z +wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ +fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD +VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G +CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1 +7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn +8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs +ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT +ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/ +2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIH/zCCB2igAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm +SVBTIENBIENMQVNFQTMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT +JklQUyBDQSBDTEFTRUEzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI +hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjMxMTEyMzU5WhcNMjUxMjI5 +MTEyMzU5WjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMFh+lWUEmnBK5F6da6IALvvPO6f +MWYw9LFAmwJsjcdKTVElPugUKLwgPLHxjO19kdmXIqPVzGOxq9krIwvdppffBYRU +Fro6y8xja40gpdaeBXFGdVj19mR7C2adPoeVPTy1OTdSVLsWF8W/rdiLMy/p+PrV +gTP/t56Fpu9MOeDjAgMBAAGjggRbMIIEVzAdBgNVHQ4EFgQU/J6FGtwGJXEh8C+L +ElXQxYDuBq4wggFGBgNVHSMEggE9MIIBOYAU/J6FGtwGJXEh8C+LElXQxYDuBq6h +ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC +AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF +BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB +BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg +hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud +EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBDBglghkgBhvhCAQ0ENhY0Q0xBU0VBMyBD +QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cHM6Ly93d3cuaXBzLmVzLzAqBglg +hkgBhvhCAQIEHRYbaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDwGCWCGSAGG ++EIBBAQvFi1odHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VB +My5jcmwwQQYJYIZIAYb4QgEDBDQWMmh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMyMDAy +L3Jldm9jYXRpb25DTEFTRUEzLmh0bWw/MD4GCWCGSAGG+EIBBwQxFi9odHRwczov +L3d3dy5pcHMuZXMvaXBzMjAwMi9yZW5ld2FsQ0xBU0VBMy5odG1sPzA8BglghkgB +hvhCAQgELxYtaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VB +My5odG1sMHcGA1UdHwRwMG4wM6AxoC+GLWh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMy +MDAyL2lwczIwMDJDTEFTRUEzLmNybDA3oDWgM4YxaHR0cHM6Ly93d3diYWNrLmlw +cy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRUEzLmNybDAvBggrBgEFBQcBAQQjMCEw +HwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQAD +gYEAGG8JN0Ca0pQR0X/Lg33qtKfi2JPe2iRqdRswDoL3CTn+bRN20V/wbKDAwyxc +7eJOroysytPkEF4wZhipaKCjaWJROZGCeU1jM7mZe9pQPzeofT//VLi8zKaUA4lZ +BvYI44gntZQoaFxJna5NHHde+mbbPYlHb8c6g0mf9S3tODs= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIDAOJCMA0GCSqGSIb3DQEBBQUAMFUxCzAJBgNVBAYTAkFU +MRAwDgYDVQQKEwdBLVRydXN0MRkwFwYDVQQLExBBLVRydXN0LW5RdWFsLTAxMRkw +FwYDVQQDExBBLVRydXN0LW5RdWFsLTAxMB4XDTA0MTEzMDIzMDAwMFoXDTE0MTEz +MDIzMDAwMFowVTELMAkGA1UEBhMCQVQxEDAOBgNVBAoTB0EtVHJ1c3QxGTAXBgNV +BAsTEEEtVHJ1c3QtblF1YWwtMDExGTAXBgNVBAMTEEEtVHJ1c3QtblF1YWwtMDEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD/9RyAEZ6eHmhYzNJ328f0 +jmdSUFi6EqRqOxb3jHNPTIpK82CR6z5lmSnZQNUuCPD+htbNZffd2DKVB06NOyZ1 +2zcOMCgj4GtkZoqE0zPpPT3bpoE55nkZZe/qWEX/64wz/L/4EdkvKDSKG/UsP75M +tmCVY5m2Eg73RVFRz4ccBIMpHel4lzEqSkdDtZOY5fnkrE333hx67nxq21vY8Eyf +8O4fPQ5RtN8eohQCcPQ1z6ypU1R7N9jPRpnI+yzMOiwd3+QcKhHi1miCzo0pkOaB +1CwmfsTyNl8qU0NJUL9Ta6cea7WThwTiWol2yD88cd2cy388xpbNkfrCPmZNGLoV +AgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECE5ZzscCMocwMA4G +A1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEA69I9R1hU9Gbl9vV7W7AH +QpUJAlFAvv2It/eY8p2ouQUPVaSZikaKtAYrCD/arzfXB43Qet+dM6CpHsn8ikYR +vQKePjXv3Evf+C1bxwJAimcnZV6W+bNOTpdo8lXljxkmfN+Z5S+XzvK2ttUtP4Et +YOVaxHw2mPMNbvDeY+foJkiBn3KYjGabMaR8moZqof5ofj4iS/WyamTZti6v/fKx +n1vII+/uWkcxV5DT5+r9HLon0NYF0Vg317Wh+gWDV59VZo+dcwJDb+keYqMFYoqp +77SGkZGu41S8NGYkQY3X9rNHRkDbLfpKYDmy6NanpOE1EHW1/sNSFAs43qZZKJEQ +xg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDMDCCApmgAwIBAgIQDY4VEuGsu3eNOOMk34ww8jANBgkqhkiG9w0BAQUFADCB +yzELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJ +Q2FwZSBUb3duMRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3Rl +IFBlcnNvbmFsIEJhc2ljIENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNp +Y0B0aGF3dGUuY29tMB4XDTk2MDEwMTAwMDAwMFoXDTIxMDEwMTIzNTk1OVowgcsx +CzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNh +cGUgVG93bjEaMBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0Nl +cnRpZmljYXRpb24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQ +ZXJzb25hbCBCYXNpYyBDQTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNA +dGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+C +FeZIlDWmWr5vQvoPR+53dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeV +oQxN2jSQHReJl+A1OFdKwPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlW +Cy4cgNrx454p7xS9CkT7G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB +/zANBgkqhkiG9w0BAQUFAAOBgQCIO/64+XpCRhGgpKJkhc1IHJzVilHNL8F9sQfP +1wHeMj+W5IT+0V6tDH4OY0lqDhDkl9A/xacp2aZTHkseP1T6wIQ1c+qRqdxdk1cF +BgwHua8LRDmIIaDugnOpRi9pbCV0qc3fp9f9hTAElDVKpxszJCxEFu0KxN+AqmUa +v3Em8A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs +ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw +MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj +aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg +nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 +HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N +Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN +dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 +HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G +CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU +sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 +4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg +8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 +mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEgzCCA+ygAwIBAgIEOJ725DANBgkqhkiG9w0BAQQFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9HQ0NBX0NQUyBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAyMDAw +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVu +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAyMDcxNjE2NDBaFw0yMDAy +MDcxNjQ2NDBaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0dDQ0FfQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDIwMDAgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCTdLS25MVL1qFof2LV7PdRV7Ny +Spj10InJrWPNTTVRaoTUrcloeW+46xHbh65cJFET8VQlhK8pK5/jgOLZy93GRUk0 +iJBeAZfv6lOm3fzB3ksqJeTpNfpVBQbliXrqpBFXO/x8PTbNZzVtpKklWb1m9fkn +5JVn1j+SgF7yNH0rhQIDAQABo4IBnjCCAZowEQYJYIZIAYb4QgEBBAQDAgAHMIHd +BgNVHR8EgdUwgdIwgc+ggcyggcmkgcYwgcMxFDASBgNVBAoTC0VudHJ1c3QubmV0 +MUAwPgYDVQQLFDd3d3cuZW50cnVzdC5uZXQvR0NDQV9DUFMgaW5jb3JwLiBieSBy +ZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0Lm5l +dCBMaW1pdGVkMTMwMQYDVQQDEypFbnRydXN0Lm5ldCBDbGllbnQgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMDAy +MDcxNjE2NDBagQ8yMDIwMDIwNzE2NDY0MFowCwYDVR0PBAQDAgEGMB8GA1UdIwQY +MBaAFISLdP3FjcD/J20gN0V8/i3OutN9MB0GA1UdDgQWBBSEi3T9xY3A/ydtIDdF +fP4tzrrTfTAMBgNVHRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4w +AwIEkDANBgkqhkiG9w0BAQQFAAOBgQBObzWAO9GK9Q6nIMstZVXQkvTnhLUGJoMS +hAusO7JE7r3PQNsgDrpuFOow4DtifH+La3xKp9U1PL6oXOpLu5OOgGarDyn9TS2/ +GpsKkMWr2tGzhtQvJFJcem3G8v7lTRowjJDyutdKPkN+1MhQGof4T4HHdguEOnKd +zmVml64mXg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL +EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ +BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x +ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg +bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ +j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV +Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG +SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx +JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI +RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw +MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5 +fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i ++DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG +SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN +QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+ +gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 +nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex +t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz +SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG +BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ +rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ +NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH +BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv +MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE +p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y +5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK +WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ +4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N +hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIESzCCAzOgAwIBAgIJAJigUTEEXRQpMA0GCSqGSIb3DQEBBQUAMHYxCzAJBgNV +BAYTAkRFMQ8wDQYDVQQIEwZIZXNzZW4xDjAMBgNVBAcTBUZ1bGRhMRAwDgYDVQQK +EwdEZWJjb25mMRMwEQYDVQQDEwpEZWJjb25mIENBMR8wHQYJKoZIhvcNAQkBFhBq +b2VyZ0BkZWJpYW4ub3JnMB4XDTA1MTEwNTE3NTUxNFoXDTE1MTEwMzE3NTUxNFow +djELMAkGA1UEBhMCREUxDzANBgNVBAgTBkhlc3NlbjEOMAwGA1UEBxMFRnVsZGEx +EDAOBgNVBAoTB0RlYmNvbmYxEzARBgNVBAMTCkRlYmNvbmYgQ0ExHzAdBgkqhkiG +9w0BCQEWEGpvZXJnQGRlYmlhbi5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCvbOo0SrIwI5IMlsshH8WF3dHB9r9JlSKhMPaybawa1EyvZspMQ3wa +F5qxNf3Sj+NElEmjseEqvCZiIIzqwerHu0Qw62cDYCdCd2+Wb5m0bPYB5CGHiyU1 +eNP0je42O0YeXG2BvUujN8AviocVo39X2YwNQ0ryy4OaqYgm2pRlbtT2ESbF+SfV +Y2iqQj/f8ymF+lHo/pz8tbAqxWcqaSiHFAVQJrdqtFhtoodoNiE3q76zJoUkZTXB +k60Yc3MJSnatZCpnsSBr/D7zpntl0THrUjjtdRWCjQVhqfhM1yZJV+ApbLdheFh0 +ZWlSxdnp25p0q0XYw/7G92ELyFDfBUUNAgMBAAGjgdswgdgwHQYDVR0OBBYEFMuV +dFNb4mCWUFbcP5LOtxFLrEVTMIGoBgNVHSMEgaAwgZ2AFMuVdFNb4mCWUFbcP5LO +txFLrEVToXqkeDB2MQswCQYDVQQGEwJERTEPMA0GA1UECBMGSGVzc2VuMQ4wDAYD +VQQHEwVGdWxkYTEQMA4GA1UEChMHRGViY29uZjETMBEGA1UEAxMKRGViY29uZiBD +QTEfMB0GCSqGSIb3DQEJARYQam9lcmdAZGViaWFuLm9yZ4IJAJigUTEEXRQpMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGZXxHg4mnkvilRIM1EQfGdY +S5b/WcyF2MYSTeTvK4aIB6VHwpZoZCnDGj2m2D3CkHT0upAD9o0zM1tdsfncLzV+ +mDT/jNmBtYo4QXx5vEPwvEIcgrWjwk7SyaEUhZjtolTkHB7ACl0oD0r71St4iEPR +qTUCEXk2E47bg1Fz58wNt/yo2+4iqiRjg1XCH4evkQuhpW+dTZnDyFNqwSYZapOE +TBA+9zBb6xD1KM2DdY7r4GiyYItN0BKLfuWbh9LXGbl1C+f4P11g+m2MPiavIeCe +1iazG5pcS3KoTLACsYlEX24TINtg4kcuS81XdllcnsV3Kdts0nIqPj6uhTTZD0k= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh +c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05 +NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD +VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp +bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB +jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N +H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR +4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN +BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo +EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5 +FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx +lA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv +b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH +iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS +r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 +04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r +GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 +3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P +lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY +MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t +dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 +WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD +VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 +9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ +DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 +Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N +QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ +xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G +A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG +kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr +Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 +Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU +JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot +RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID2TCCAsGgAwIBAgIDAjbQMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMTAwMjE5MjIzOTI2WhcNMjAwMjE4MjIzOTI2WjBAMQswCQYDVQQG +EwJVUzEXMBUGA1UEChMOR2VvVHJ1c3QsIEluYy4xGDAWBgNVBAMTD0dlb1RydXN0 +IFNTTCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJCzgMHk5Uat +cGA9uuUU3Z6KXot1WubKbUGlI+g5hSZ6p1V3mkihkn46HhrxJ6ujTDnMyz1Hr4Gu +FmpcN+9FQf37mpc8oEOdxt8XIdGKolbCA0mEEoE+yQpUYGa5jFTk+eb5lPHgX3UR +8im55IaisYmtph6DKWOy8FQchQt65+EuDa+kvc3nsVrXjAVaDktzKIt1XTTYdwvh +dGLicTBi2LyKBeUxY0pUiWozeKdOVSQdl+8a5BLGDzAYtDRN4dgjOyFbLTAZJQ50 +96QhS6CkIMlszZhWwPKoXz4mdaAN+DaIiixafWcwqQ/RmXAueOFRJq9VeiS+jDkN +d53eAsMMvR8CAwEAAaOB2TCB1jAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFEJ5 +VBthzVUrPmPVPEhX9Z/7Rc5KMB8GA1UdIwQYMBaAFMB6mGiNifurBWQMEX2qfWW4 +ysxOMBIGA1UdEwEB/wQIMAYBAf8CAQAwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDov +L2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwNAYIKwYBBQUHAQEE +KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5nZW90cnVzdC5jb20wDQYJKoZI +hvcNAQEFBQADggEBANTvU4ToGr2hiwTAqfVfoRB4RV2yV2pOJMtlTjGXkZrUJPji +J2ZwMZzBYlQG55cdOprApClICq8kx6jEmlTBfEx4TCtoLF0XplR4TEbigMMfOHES +0tdT41SFULgCy+5jOvhWiU1Vuy7AyBh3hjELC3DwfjWDpCoTZFZnNF0WX3OsewYk +2k9QbSqr0E1TQcKOu3EDSSmGGM8hQkx0YlEVxW+o78Qn5Rsz3VqI138S0adhJR/V +4NwdzxoQ2KDLX4z6DOW/cf/lXUQdpj6HR/oaToODEj+IZpWYeZqF6wJHzSXj8gYE +TpnKXKBuervdo5AaRTPvvz7SBMS24CqFZUE+ENQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDdjCCAl6gAwIBAgIEOhsEBTANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJE +SzEMMAoGA1UEChMDS01EMQ8wDQYDVQQLEwZLTUQtQ0ExIzAhBgNVBAMTGktNRC1D +QSBLdmFsaWZpY2VyZXQgUGVyc29uMB4XDTAwMTEyMTIzMjQ1OVoXDTE1MTEyMjIz +MjQ1OVowUTELMAkGA1UEBhMCREsxDDAKBgNVBAoTA0tNRDEPMA0GA1UECxMGS01E +LUNBMSMwIQYDVQQDExpLTUQtQ0EgS3ZhbGlmaWNlcmV0IFBlcnNvbjCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBANriF4Xd6yD7ZlBE317UBDObn+vRMVc6 +p3wNQODdEDJe2z1ncCz9NJvhoLGdOJhyg7VVPh0P2c+KZ9WI9mWOKZI2bp2WkLju +jCcxbhTrurY3Wfc6gwLBqqFV8wWgaZKmvVWizjw9Kyi25f3yX4fOho6Qq2lvVbub +tvVFXAd51GJ+/2Yed+a4Or2bz2RcqHS81B3pywsD4mgJR5xREv5jqPfwNP+V7bkc +X+pfO4kVhZ/V+8MSPdQHgcV/iB3wP2mwgWyIBNc1reBidGTiz8unnWu55hcNfsvt +LJbTs9OHhsR7naRuy+S402nDnD5vnONOFEsiHn46w+T0rtu7h6j4OvkCAwEAAaNW +MFQwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUeWLqmhI42Jxj7DifDsW+ +DlQhKD0wHwYDVR0jBBgwFoAUeWLqmhI42Jxj7DifDsW+DlQhKD0wDQYJKoZIhvcN +AQEFBQADggEBANML/P42OuJ9aUV/0fItuIyc1JhqWvSqn5bXj+9eyEegcp8bHLHY +42D1O+z0lNipdjYPSdMJ0wZOEUhr+150SdDQ1P/zQL8AUaLEBkRt7ZdzXPVH3PER +qnf9IrpYBknZKfCAoVchA6Rr9WU3Sd8bMoRfMLKg8c0M8G6EPwCTcOFriSkbtvNG +zd8r8I+WfUYIN/p8DI9JT9qfjVODnYPRMUm6KPvq27TsrGruKrqyaV94kWc8co8A +v3zFLeCtghvUiRBdx+8Q7m5t4CkuSr0WINrqjIPFW2QrM1r82y09Fd16RkqL4LOg +Lh6vB5KnTApv62rWdw7zWwYnjY6/vXYY1Aw= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGCDCCA/CgAwIBAgIBATANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 +IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB +IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA +Y2FjZXJ0Lm9yZzAeFw0wNTEwMTQwNzM2NTVaFw0zMzAzMjgwNzM2NTVaMFQxFDAS +BgNVBAoTC0NBY2VydCBJbmMuMR4wHAYDVQQLExVodHRwOi8vd3d3LkNBY2VydC5v +cmcxHDAaBgNVBAMTE0NBY2VydCBDbGFzcyAzIFJvb3QwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCrSTURSHzSJn5TlM9Dqd0o10Iqi/OHeBlYfA+e2ol9 +4fvrcpANdKGWZKufoCSZc9riVXbHF3v1BKxGuMO+f2SNEGwk82GcwPKQ+lHm9WkB +Y8MPVuJKQs/iRIwlKKjFeQl9RrmK8+nzNCkIReQcn8uUBByBqBSzmGXEQ+xOgo0J +0b2qW42S0OzekMV/CsLj6+YxWl50PpczWejDAz1gM7/30W9HxM3uYoNSbi4ImqTZ +FRiRpoWSR7CuSOtttyHshRpocjWr//AQXcD0lKdq1TuSfkyQBX6TwSyLpI5idBVx +bgtxA+qvFTia1NIFcm+M+SvrWnIl+TlG43IbPgTDZCciECqKT1inA62+tC4T7V2q +SNfVfdQqe1z6RgRQ5MwOQluM7dvyz/yWk+DbETZUYjQ4jwxgmzuXVjit89Jbi6Bb +6k6WuHzX1aCGcEDTkSm3ojyt9Yy7zxqSiuQ0e8DYbF/pCsLDpyCaWt8sXVJcukfV +m+8kKHA4IC/VfynAskEDaJLM4JzMl0tF7zoQCqtwOpiVcK01seqFK6QcgCExqa5g +eoAmSAC4AcCTY1UikTxW56/bOiXzjzFU6iaLgVn5odFTEcV7nQP2dBHgbbEsPyyG +kZlxmqZ3izRg0RS0LKydr4wQ05/EavhvE/xzWfdmQnQeiuP43NJvmJzLR5iVQAX7 +6QIDAQABo4G/MIG8MA8GA1UdEwEB/wQFMAMBAf8wXQYIKwYBBQUHAQEEUTBPMCMG +CCsGAQUFBzABhhdodHRwOi8vb2NzcC5DQWNlcnQub3JnLzAoBggrBgEFBQcwAoYc +aHR0cDovL3d3dy5DQWNlcnQub3JnL2NhLmNydDBKBgNVHSAEQzBBMD8GCCsGAQQB +gZBKMDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuQ0FjZXJ0Lm9yZy9pbmRleC5w +aHA/aWQ9MTAwDQYJKoZIhvcNAQEEBQADggIBAH8IiKHaGlBJ2on7oQhy84r3HsQ6 +tHlbIDCxRd7CXdNlafHCXVRUPIVfuXtCkcKZ/RtRm6tGpaEQU55tiKxzbiwzpvD0 +nuB1wT6IRanhZkP+VlrRekF490DaSjrxC1uluxYG5sLnk7mFTZdPsR44Q4Dvmw2M +77inYACHV30eRBzLI++bPJmdr7UpHEV5FpZNJ23xHGzDwlVks7wU4vOkHx4y/CcV +Bc/dLq4+gmF78CEQGPZE6lM5+dzQmiDgxrvgu1pPxJnIB721vaLbLmINQjRBvP+L +ivVRIqqIMADisNS8vmW61QNXeZvo3MhN+FDtkaVSKKKs+zZYPumUK5FQhxvWXtaM +zPcPEAxSTtAWYeXlCmy/F8dyRlecmPVsYGN6b165Ti/Iubm7aoW8mA3t+T6XhDSU +rgCvoeXnkm5OvfPi2RSLXNLrAWygF6UtEOucekq9ve7O/e0iQKtwOIj1CodqwqsF +YMlIBdpTwd5Ed2qz8zw87YC8pjhKKSRf/lk7myV6VmMAZLldpGJ9VzZPrYPvH5JT +oI53V93lYRE9IwCQTDz6o2CTBKOvNfYOao9PSmCnhQVsRqGP9Md246FZV/dxssRu +FFxtbUFm3xuTsdQAw+7Lzzw9IYCpX2Nl/N3gX6T0K/CFcUHUZyX7GrGXrtaZghNB +0m6lG5kngOcLqagA +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIF8DCCA9igAwIBAgIPBuhGJy8fCo/RhFzjafbVMA0GCSqGSIb3DQEBBQUAMDgx +CzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXpl +bnBlLmNvbTAeFw0wNzEyMTMxMzA4MjdaFw0zNzEyMTMwODI3MjVaMDgxCzAJBgNV +BAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXplbnBlLmNv +bTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMnTesoPHqynhugWZWqx +whtFMnGV2f4QW8yv56V5AY+Jw8ryVXH3d753lPNypCxE2J6SmxQ6oeckkAoKVo7F +2CaU4dlI4S0+2gpy3aOZFdqBoof0e24md4lYrdbrDLJBenNubdt6eEHpCIgSfocu +ZhFjbFT7PJ1ywLwu/8K33Q124zrX97RovqL144FuwUZvXY3gTcZUVYkaMzEKsVe5 +o4qYw+w7NMWVQWl+dcI8IMVhulFHoCCQk6GQS/NOfIVFVJrRBSZBsLVNHTO+xAPI +JXzBcNs79AktVCdIrC/hxKw+yMuSTFM5NyPs0wH54AlETU1kwOENWocivK0bo/4m +tRXzp/yEGensoYi0RGmEg/OJ0XQGqcwL1sLeJ4VQJsoXuMl6h1YsGgEebL4TrRCs +tST1OJGh1kva8bvS3ke18byB9llrzxlT6Y0Vy0rLqW9E5RtBz+GGp8rQap+8TI0G +M1qiheWQNaBiXBZO8OOi+gMatCxxs1gs3nsL2xoP694hHwZ3BgOwye+Z/MC5TwuG +KP7Suerj2qXDR2kS4Nvw9hmL7Xtw1wLW7YcYKCwEJEx35EiKGsY7mtQPyvp10gFA +Wo15v4vPS8+qFsGV5K1Mij4XkdSxYuWC5YAEpAN+jb/af6IPl08M0w3719Hlcn4c +yHf/W5oPt64FRuXxqBbsR6QXAgMBAAGjgfYwgfMwgbAGA1UdEQSBqDCBpYEPaW5m +b0BpemVucGUuY29tpIGRMIGOMUcwRQYDVQQKDD5JWkVOUEUgUy5BLiAtIENJRiBB +MDEzMzcyNjAtUk1lcmMuVml0b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFDMEEG +A1UECQw6QXZkYSBkZWwgTWVkaXRlcnJhbmVvIEV0b3JiaWRlYSAxNCAtIDAxMDEw +IFZpdG9yaWEtR2FzdGVpejAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUHRxlDqjyJXu0kc/ksbHmvVV0bAUwDQYJKoZIhvcNAQEFBQAD +ggIBAMeBRm8hGE+gBe/n1bqXUKJg7aWSFBpSm/nxiEqg3Hh10dUflU7F57dp5iL0 ++CmoKom+z892j+Mxc50m0xwbRxYpB2iEitL7sRskPtKYGCwkjq/2e+pEFhsqxPqg +l+nqbFik73WrAGLRne0TNtsiC7bw0fRue0aHwp28vb5CO7dz0JoqPLRbEhYArxk5 +ja2DUBzIgU+9Ag89njWW7u/kwgN8KRwCfr00J16vU9adF79XbOnQgxCvv11N75B7 +XSus7Op9ACYXzAJcY9cZGKfsK8eKPlgOiofmg59OsjQerFQJTx0CCzl+gQgVuaBp +E8gyK+OtbBPWg50jLbJtooiGfqgNASYJQNntKE6MkyQP2/EeTXp6WuKlWPHcj1+Z +ggwuz7LdmMySlD/5CbOlliVbN/UShUHiGUzGigjB3Bh6Dx4/glmimj4/+eAJn/3B +kUtdyXvWton83x18hqrNA/ILUpLxYm9/h+qrdslsUMIZgq+qHfUgKGgu1fxkN0/P +pUTEvnK0jHS0bKf68r10OEMr3q/53NjgnZ/cPcqlY0S/kqJPTIAcuxrDmkoEVU3K +7iYLHL8CxWTTnn7S05EcS6L1HOUXHA0MUqORH5zwIe0ClG+poEnK6EOMxPQ02nwi +o8ZmPrgbBYhdurz3vOXcFD2nhqi2WVIhA16L4wTtSyoeo09Q +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICsDCCAhmgAwIBAgIQZ8jh6OO+HL38kTuOpiOHSTANBgkqhkiG9w0BAQUFADCB +izELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxML +RHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENl +cnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcN +OTcwMTAxMDAwMDAwWhcNMjEwMTAxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTAT +BgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNV +BAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNV +BAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0A +MIGJAoGBANYrWHhhRYZT6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u +6TqFJBU820cEY8OexJQaWt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522 +FOMjhdepQeBMpHmwKxqL8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzAR +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAS+mqF4EF+3kKMZ/F +QfRWVKvpwuWXjhj+kckMPiZkyaFMJ2SnvQGTVXFuF0853BvcSTUQOSP/ypvIz2Y/ +3Ewa1IEGQlIf4SaxFhe65nByMUToTo1b5NP50OOPJWQx5yr4GIg2GlLFDUE1G2m3 +JvUXzMEZXkt8XOKDgJH6L/uatxY= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDtDCCApygAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJKUDEc +MBoGA1UEChMTSmFwYW5lc2UgR292ZXJubWVudDEOMAwGA1UECxMFTVBIUFQxJjAk +BgNVBAsTHU1QSFBUIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTAyMDMxNDA3 +NTAyNloXDTEyMDMxMzE0NTk1OVowYzELMAkGA1UEBhMCSlAxHDAaBgNVBAoTE0ph +cGFuZXNlIEdvdmVybm1lbnQxDjAMBgNVBAsTBU1QSFBUMSYwJAYDVQQLEx1NUEhQ +VCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAI3GUWlK9G9FVm8DhpKu5t37oxZbj6lZcFvEZY07YrYojWO657ub +z56WE7q/PI/6Sm7i7qYE+Vp80r6thJvfmn7SS3BENrRqiapSenhooYD12jIe3iZQ +2SXqx7WgYwyBGdQwGaYTijzbRFpgc0K8o4a99fIoHhz9J8AKqXasddMCqfJRaH30 +YJ7HnOvRYGL6HBrGhJ7X4Rzijyk9a9+3VOBsYcnIlx9iODoiYhA6r0ojuIu8/JA1 +oTTZrS0MyU/SLdFdJze2O1wnqTULXQybzJz3ad6oC/F5a69c0m92akYd9nGBrPxj +EhucaQynC/QoCLs3aciLgioAnEJqy7i3EgUCAwEAAaNzMHEwHwYDVR0jBBgwFoAU +YML3pLoA0h93Yngl8Gb/UgAh73owHQYDVR0OBBYEFGDC96S6ANIfd2J4JfBm/1IA +Ie96MAwGA1UdEwQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQE +AwIABTANBgkqhkiG9w0BAQUFAAOCAQEANPR8DN66iWZBs/lSm1vOzhqRkXDLT6xL +LvJtjPLqmE469szGyFSKzsof6y+/8YgZlOoeX1inF4ox/SH1ATnwdIIsPbXuRLjt +axboXvBh5y2ffC3hmzJVvJ87tb6mVWQeL9VFUhNhAI0ib+9OIZVEYI/64MFkDk4e +iWG5ts6oqIJH1V7dVZg6pQ1Tc0Ckhn6N1m1hD30S0/zoPn/20Wq6OCF3he8VJrRG +dcW9BD/Bkesko1HKhMBDjHVrJ8cFwbnDSoo+Ki47eJWaz/cOzaSsaMVUsR5POava +/abhhgHn/eOJdXiVslyK0DYscjsdB3aBUfwZlomxYOzG6CgjQPhJdw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEejCCA2KgAwIBAgIEP4vk6TANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJQ +TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu +dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQgLSBD +QSBLbGFzYSAyMB4XDTAzMTAxNDExNTgyMloXDTE3MDQxODEyNTMwN1owdzELMAkG +A1UEBhMCUEwxHzAdBgNVBAoTFlRQIEludGVybmV0IFNwLiB6IG8uby4xJDAiBgNV +BAsTG0NlbnRydW0gQ2VydHlmaWthY2ppIFNpZ25ldDEhMB8GA1UEAxMYQ0MgU2ln +bmV0IC0gT0NTUCBLbGFzYSAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCo +VCsaBStblXQYVNthe3dvaCrfvKpPXngh4almm988iIlEv9CVTaAdCfaJNihvA+Vs +Qw8++ix1VqteMQE474/MV/YaXigP0Zr0QB+g+/7PWVlv+5U9Gzp9+Xx4DJay8AoI +iB7Iy5Qf9iZiHm5BiPRIuUXT4ZRbZRYPh0/76vgRsQIDAQABo4IBkjCCAY4wDgYD +VR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMJMEEGA1UdHwQ6MDgwNqA0 +oDKGMGh0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9jcmwva2xhc2Ey +LmNybDCB2AYDVR0gBIHQMIHNMIHKBg4rBgEEAb4/AoFICgwBADCBtzBsBggrBgEF +BQcCAjBgGl5DZXJ0eWZpa2F0IHd5ZGFueSB6Z29kbmllIHogZG9rdW1lbnRlbSAi +UG9saXR5a2EgQ2VydHlmaWthY2ppIC0gQ2VydHlmaWthdHkgcmVzcG9uZGVyb3cg +T0NTUCIuMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnNpZ25ldC5wbC9yZXBvenl0 +b3JpdW0vZG9rdW1lbnR5L3BjX29jc3BfMV8wLnBkZjAfBgNVHSMEGDAWgBS7RQZS +C8uBzSlUs7x8QUzNBw6MJTAdBgNVHQ4EFgQUKEVrOY7cEHvsVgvoyZdytlbtgwEw +CQYDVR0TBAIwADANBgkqhkiG9w0BAQUFAAOCAQEAQrRg5MV6dxr0HU2IsLInxhvt +iUVmSFkIUsBCjzLoewOXA16d2oDyHhI/eE+VgAsp+2ANjZu4xRteHIHoYMsN218M +eD2MLRsYS0U9xxAFK9gDj/KscPbrrdoqLvtPSMhUb4adJS9HLhvUe6BicvBf3A71 +iCNe431axGNDWKnpuj2KUpj4CFHYsWCXky847YtTXDjri9NIwJJauazsrSjK+oXp +ngRS506mdQ7vWrtApkh8zhhWp7duCkjcCo1O8JxqYr2qEW1fXmgOISe010v2mmuv +hHxPyVwoAU4KkOw0nbXZn53yak0is5+XmAjh0wWue44AssHrjC9nUh3mkLt6eQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz +MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv +cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz +Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO +0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao +wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj +7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS +8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT +BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg +JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 +6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ +3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm +D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS +CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIIODCCB6GgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCAR4xCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjE0MDIGA1UECxMr +SVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE0MDIG +A1UEAxMrSVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eTEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAxMTAx +OFoXDTI1MTIyNzAxMTAxOFowggEeMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFy +Y2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5l +dCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlw +cy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxNDAyBgNVBAsTK0lQUyBDQSBUaW1lc3Rh +bXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxNDAyBgNVBAMTK0lQUyBDQSBU +aW1lc3RhbXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHjAcBgkqhkiG9w0B +CQEWD2lwc0BtYWlsLmlwcy5lczCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA +vLjuVqWajOY2ycJioGaBjRrVetJznw6EZLqVtJCneK/K/lRhW86yIFcBrkSSQxA4 +Efdo/BdApWgnMjvEp+ZCccWZ73b/K5Uk9UmSGGjKALWkWi9uy9YbLA1UZ2t6KaFY +q6JaANZbuxjC3/YeE1Z2m6Vo4pjOxgOKNNtMg0GmqaMCAwEAAaOCBIAwggR8MB0G +A1UdDgQWBBSL0BBQCYHynQnVDmB4AyKiP8jKZjCCAVAGA1UdIwSCAUcwggFDgBSL +0BBQCYHynQnVDmB4AyKiP8jKZqGCASakggEiMIIBHjELMAkGA1UEBhMCRVMxEjAQ +BgNVBAgTCUJhcmNlbG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJ +UFMgSW50ZXJuZXQgcHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJp +cHNAbWFpbC5pcHMuZXMgQy5JLkYuICBCLTYwOTI5NDUyMTQwMgYDVQQLEytJUFMg +Q0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTQwMgYDVQQD +EytJUFMgQ0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4w +HAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAM +BgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYB +BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIB +FgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYD +VR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlw +cy5lczBHBglghkgBhvhCAQ0EOhY4VGltZXN0YW1waW5nIENBIENlcnRpZmljYXRl +IGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgECBBwWGmh0 +dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMEAGCWCGSAGG+EIBBAQzFjFodHRwOi8v +d3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMEUGCWCG +SAGG+EIBAwQ4FjZodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25U +aW1lc3RhbXBpbmcuaHRtbD8wQgYJYIZIAYb4QgEHBDUWM2h0dHA6Ly93d3cuaXBz +LmVzL2lwczIwMDIvcmVuZXdhbFRpbWVzdGFtcGluZy5odG1sPzBABglghkgBhvhC +AQgEMxYxaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lUaW1lc3RhbXBp +bmcuaHRtbDB/BgNVHR8EeDB2MDegNaAzhjFodHRwOi8vd3d3Lmlwcy5lcy9pcHMy +MDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMDugOaA3hjVodHRwOi8vd3d3YmFj +ay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyVGltZXN0YW1waW5nLmNybDAvBggrBgEF +BQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZI +hvcNAQEFBQADgYEAZbrBzAAalZHK6Ww6vzoeFAh8+4Pua2JR0zORtWB5fgTYXXk3 +6MNbsMRnLWhasl8OCvrNPzpFoeo2zyYepxEoxZSPhExTCMWTs/zif/WN87GphV+I +3pGW7hdbrqXqcGV4LCFkAZXOzkw+UPS2Wctjjba9GNSHSl/c7+lW8AoM6HU= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFujCCBKKgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhjELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFwcGxlIENvbXB1dGVyLCBJbmMuMS0wKwYDVQQLEyRBcHBsZSBD +b21wdXRlciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAnBgNVBAMTIEFwcGxlIFJv +b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA1MDIxMDAwMTgxNFoXDTI1MDIx +MDAwMTgxNFowgYYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBcHBsZSBDb21wdXRl +ciwgSW5jLjEtMCsGA1UECxMkQXBwbGUgQ29tcHV0ZXIgQ2VydGlmaWNhdGUgQXV0 +aG9yaXR5MSkwJwYDVQQDEyBBcHBsZSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 +eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOSRqQkfkdseR1DrBe1e +eYQt6zaiV0xV7IsZid75S2z1B6siMALoGD74UAnTf0GomPnRymacJGsR0KO75Bsq +wx+VnnoMpEeLW9QWNzPLxA9NzhRp0ckZcvVdDtV/X5vyJQO6VY9NXQ3xZDUjFUsV +WR2zlPf2nJ7PULrBWFBnjwi0IPfLrCwgb3C2PwEwjLdDzw+dPfMrSSgayP7OtbkO +2V4c1ss9tTqt9A8OAJILsSEWLnTVPA3bYharo3GSR1NVwa8vQbP4++NwzeajTEV+ +H0xrUJZBicR0YgsQg0GHM4qBsTBY7FoEMoxos48d3mVz/2deZbxJ2HafMxRloXeU +yS0CAwEAAaOCAi8wggIrMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ +MB0GA1UdDgQWBBQr0GlHlHYJ/vRrjS5ApvdHTX8IXjAfBgNVHSMEGDAWgBQr0GlH +lHYJ/vRrjS5ApvdHTX8IXjCCASkGA1UdIASCASAwggEcMIIBGAYJKoZIhvdjZAUB +MIIBCTBBBggrBgEFBQcCARY1aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmlj +YXRlYXV0aG9yaXR5L3Rlcm1zLmh0bWwwgcMGCCsGAQUFBwICMIG2GoGzUmVsaWFu +Y2Ugb24gdGhpcyBjZXJ0aWZpY2F0ZSBieSBhbnkgcGFydHkgYXNzdW1lcyBhY2Nl +cHRhbmNlIG9mIHRoZSB0aGVuIGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5k +IGNvbmRpdGlvbnMgb2YgdXNlLCBjZXJ0aWZpY2F0ZSBwb2xpY3kgYW5kIGNlcnRp +ZmljYXRpb24gcHJhY3RpY2Ugc3RhdGVtZW50cy4wRAYDVR0fBD0wOzA5oDegNYYz +aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L3Jvb3Qu +Y3JsMFUGCCsGAQUFBwEBBEkwRzBFBggrBgEFBQcwAoY5aHR0cHM6Ly93d3cuYXBw +bGUuY29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L2Nhc2lnbmVycy5odG1sMA0GCSqG +SIb3DQEBBQUAA4IBAQCd2i0oWC99dgS5BNM+zrdmY06PL9T+S61yvaM5xlJNBZhS +9YlRASR5vhoy9+VEi0tEBzmC1lrKtCBe2a4VXR2MHTK/ODFiSF3H4ZCx+CRA+F9Y +m1FdV53B5f88zHIhbsTp6aF31ywXJsM/65roCwO66bNKcuszCVut5mIxauivL9Wv +Hld2j383LS4CXN1jyfJxuCZA3xWNdUQ/eb3mHZnhQyw+rW++uaT+DjUZUWOxw961 +kj5ReAFziqQjyqSI8R5cH0EWLX6VCqrpiUGYGxrdyyC/R14MJsVVNU3GMIuZZxTH +CR+6R8faAQmHJEKVvRNgGQrv6n8Obs3BREM6StXj +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezEL +MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV +BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1 +c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAeFw0wOTA5MDkwODE1MjdaFw0yOTEy +MzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNUQyBUcnVzdENlbnRl +ciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0ExKDAm +BgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF +5+cvAqBNLaT6hdqbJYUtQCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYv +DIRlzg9uwliT6CwLOunBjvvya8o84pxOjuT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8v +zArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+EutCHnNaYlAJ/Uqwa1D7KRT +yGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1M4BDj5yj +dipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBh +MB8GA1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI +4jANBgkqhkiG9w0BAQUFAAOCAQEAg8ev6n9NCjw5sWi+e22JLumzCecYV42Fmhfz +dkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+KGwWaODIl0YgoGhnYIg5IFHY +aAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhKBgePxLcHsU0G +DeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV +CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPH +LQNjO9Po5KIqwoIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDvjCCA3ygAwIBAgIFJQaThoEwCwYHKoZIzjgEAwUAMIGFMQswCQYDVQQGEwJG +UjEPMA0GA1UECBMGRnJhbmNlMQ4wDAYDVQQHEwVQYXJpczEQMA4GA1UEChMHUE0v +U0dETjEOMAwGA1UECxMFRENTU0kxDjAMBgNVBAMTBUlHQy9BMSMwIQYJKoZIhvcN +AQkBFhRpZ2NhQHNnZG4ucG0uZ291di5mcjAeFw0wMjEyMTMxNDM5MTVaFw0yMDEw +MTcxNDM5MTRaMIGFMQswCQYDVQQGEwJGUjEPMA0GA1UECBMGRnJhbmNlMQ4wDAYD +VQQHEwVQYXJpczEQMA4GA1UEChMHUE0vU0dETjEOMAwGA1UECxMFRENTU0kxDjAM +BgNVBAMTBUlHQy9BMSMwIQYJKoZIhvcNAQkBFhRpZ2NhQHNnZG4ucG0uZ291di5m +cjCCAbYwggErBgcqhkjOOAQBMIIBHgKBgQCFkMImdk9zDzJfTO4XPdAAmLbAdWws +ZiEMZh19RyTo3CyhFqO77OIXrwY6vc1pcc3MgWJ0dgQpAgrDMtmFFxpUu4gmjVsx +8GpxQC+4VOgLY8Cvmcd/UDzYg07EIRto8BwCpPJ/JfUxwzV2V3N713aAX+cEoKZ/ +s+kgxC6nZCA7oQIVALME/JYjkdW2uKIGngsEPbXAjdhDAoGADh/uqWJx94UBm31c +9d8ZTBfRGRnmSSRVFDgPWgA69JD4BR5da8tKz+1HjfMhDXljbMH86ixpD5Ka1Z0V +pRYUPbyAoB37tsmXMJY7kjyD19d5VdaZboUjVvhH6UJy5lpNNNGSvFl4fqkxyvw+ +pq1QV0N5RcvK120hlXdfHUX+YKYDgYQAAoGAQGr7IuKJcYIvJRMjxwl43KxXY2xC +aoCiM/bv117MfI94aNf1UusGhp7CbYAY9CXuL60P0oPMAajbaTE5Z34AuITeHq3Y +CNMHwxalip8BHqSSGmGiQsXeK7T+r1rPXsccZ1c5ikGDZ4xn5gUaCyy2rCmb+fOJ +6VAfCbAbAjmNKwejdzB1MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgFGMBUG +A1UdIAQOMAwwCgYIKoF6AXkBAQEwHQYDVR0OBBYEFPkeNRcUf8idzpKblYbLNxs0 +MQhSMB8GA1UdIwQYMBaAFPkeNRcUf8idzpKblYbLNxs0MQhSMAsGByqGSM44BAMF +AAMvADAsAhRVh+CJA5eVyEYU5AO9Tm7GxX0rmQIUBCqsU5u1WxoZ5lEXicDX5/Ob +sRQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 +pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 +13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk +U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i +F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY +oJ2daZH9 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X +DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ +BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 +QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny +gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw +zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q +130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 +JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw +ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT +AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj +AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG +9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h +bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc +fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu +HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w +t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAx +MDQwNjEwNDkxM1oXDTIxMDQwNjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMSBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H887dF+2rDNbS82rDTG +29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9EJUk +oVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk +3w0LBUXl0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBL +qdReLjVQCfOAl/QMF6452F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIIN +nvmLVz5MxxftLItyM19yejhW1ebZrgUaHXVFsculJRwSVzb9IjcCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZTiFIwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE928Jj2VuX +ZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0H +DjxVyhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VO +TzF2nBBhjrZTOqMRvq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2Uv +kVrCqIexVmiUefkl98HVrhq4uz2PqYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4w +zMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9ZIRlXvVWa +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIF5jCCA86gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh +IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyOTA2MDAwMFoXDTM3MDkyODIz +NDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg +SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M +IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALQ3WggWmRToVbEbJGv8x4vmh6mJ +7ouZzU9AhqS2TcnZsdw8TQ2FTBVsRotSeJ/4I/1n9SQ6aF3Q92RhQVSji6UI0ilb +m2BPJoPRYxJWSXakFsKlnUWsi4SVqBax7J/qJBrvuVdcmiQhLE0OcR+mrF1FdAOY +xFSMFkpBd4aVdQxHAWZg/BXxD+r1FHjHDtdugRxev17nOirYlxcwfACtCJ0zr7iZ +YYCLqJV+FNwSbKTQ2O9ASQI2+W6p1h2WVgSysy0WVoaP2SBXgM1nEG2wTPDaRrbq +JS5Gr42whTg0ixQmgiusrpkLjhTXUr2eacOGAgvqdnUxCc4zGSGFQ+aJLZ8lN2fx +I2rSAG2X+Z/nKcrdH9cG6rjJuQkhn8g/BsXS6RJGAE57COtCPStIbp1n3UsC5ETz +kxmlJ85per5n0/xQpCyrw2u544BMzwVhSyvcG7mm0tCq9Stz+86QNZ8MUhy/XCFh +EVsVS6kkUfykXPcXnbDS+gfpj1bkGoxoigTTfFrjnqKhynFbotSg5ymFXQNoKk/S +Btc9+cMDLz9l+WceR0DTYw/j1Y75hauXTLPXJuuWCpTehTacyH+BCQJJKg71ZDIM +gtG6aoIbs0t0EfOMd9afv9w3pKdVBC/UMejTRrkDfNoSTllkt1ExMVCgyhwn2RAu +rda9EGYrw7AiShJbAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FE9pbQN+nZ8HGEO8txBO1b+pxCAoMB8GA1UdIwQYMBaAFE9pbQN+nZ8HGEO8txBO +1b+pxCAoMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAO/Ouyugu +h4X7ZVnnrREUpVe8WJ8kEle7+z802u6teio0cnAxa8cZmIDJgt43d15Ui47y6mdP +yXSEkVYJ1eV6moG2gcKtNuTxVBFT8zRFASbI5Rq8NEQh3q0l/HYWdyGQgJhXnU7q +7C+qPBR7V8F+GBRn7iTGvboVsNIYvbdVgaxTwOjdaRITQrcCtQVBynlQboIOcXKT +RuidDV29rs4prWPVVRaAMCf/drr3uNZK49m1+VLQTkCpx+XCMseqdiThawVQ68W/ +ClTluUI8JPu3B5wwn3la5uBAUhX0/Kr0VvlEl4ftDmVyXr4m+02kLQgH3thcoNyB +M5kYJRF3p+v9WAksmWsbivNSPxpNSGDxoPYzAlOL7SUJuA0t7Zdz7NeWH45gDtoQ +my8YJPamTQr5O8t1wswvziRpyQoijlmn94IM19drNZxDAGrElWe6nEXLuA4399xO +AU++CrYD062KRffaJ00psUjf5BHklka9bAI+1lHIlRcBFanyqqryvy9lG2/QuRqT +9Y41xICHPpQvZuTpqP9BnHAqTyo5GJUefvthATxRCC4oGKQWDzH9OmwjkyB24f0H +hdFbP9IcczLd+rn4jM8Ch3qaluTtT4mNU0OrDhPAARW0eTjb/G49nlG2uBOLZ8/5 +fNkiHfZdxRwBL5joeiQYvITX+txyW/fBOmg= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj +dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0 +NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD +VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G +vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/ +BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C +AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX +MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl +IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw +NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq +y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF +MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA +A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy +0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1 +E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw +IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL +SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH +SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh +ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X +DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 +TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ +fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA +sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU +WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS +nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH +dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip +NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC +AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF +MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB +uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl +PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP +JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ +gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 +j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 +5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB +o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS +/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z +Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE +W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D +hNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIF3zCCA8egAwIBAgIOGTMAAQACKBqaBLzyVUUwDQYJKoZIhvcNAQEFBQAwejEL +MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV +BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEnMCUGA1UEAxMeVEMgVHJ1 +c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJMB4XDTA2MDMyMjE1NTgzNFoXDTMwMTIz +MTIyNTk1OVowejELMAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVy +IEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEnMCUG +A1UEAxMeVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJMIICIjANBgkqhkiG +9w0BAQEFAAOCAg8AMIICCgKCAgEAi9R3azRs5TbYalxeOO781R15Azt7g2JEgk6I +7d6D/+7MUGIFBZWZdpj2ufJf2AaRksL2LWYXH/1TA+iojWOpbuHWG4y8mLOLO9Tk +Lsp9hUkmW3m4GotAnn+7yT9jLM/RWny6KCJBElpN+Rd3/IX9wkngKhh/6aAsnPlE +/AxoOUL1JwW+jhV6YJ3wO8c85j4WvK923mq3ouGrRkXrjGV90ZfzlxElq1nroCLZ +gt2Y7X7i+qBhCkoy3iwX921E6oFHWZdXNwM53V6CItQzuPomCba8OYgvURVOm8M7 +3xOCiN1LNPIz1pDp81PcNXzAw9l8eLPNcD+NauCjgUjkKa1juPD8KGQ7mbN9/pqd +iPaZIgiRRxaJNXhdd6HPv0nh/SSUK2k2e+gc5iqQilvVOzRZQtxtz7sPQRxVzfUN +Wy4WIibvYR6X/OJTyM9bo8ep8boOhhLLE8oVx+zkNo3aXBM9ZdIOXXB03L+PemrB +Lg/Txl4PK1lszGFs/sBhTtnmT0ayWuIZFHCE+CAA7QGnl37DvRJckiMXoKUdRRcV +I5qSCLUiiI3cKyTr4LEXaNOvYb3ZhXj2jbp4yjeNY77nrB/fpUcJucglMVRGURFV +DYlcjdrSGC1z8rjVJ/VIIjfRYvd7Dcg4i6FKsPzQ8eu3hmPn4A5zf/1yUbXpfeJV +BWR4Z38CAwEAAaNjMGEwHwYDVR0jBBgwFoAUzdeQoW6jv9sw1toyJZAM5jkegGUw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFM3XkKFu +o7/bMNbaMiWQDOY5HoBlMA0GCSqGSIb3DQEBBQUAA4ICAQB+FojoEw42zG4qhQc4 +xlaJeuNHIWZMUAgxWlHQ/KZeFHXeTDvs8e3MfhEHSmHu6rOOOqQzxu2KQmZP8Tx7 +yaUFQZmx7Cxb7tyW0ohTS3g0uW7muw/FeqZ8Dhjfbw90TNGp8aHp2FRkzF6WeKJW +GsFzshXGVwXf2vdIJIqOf2qp+U3pPmrOYCx9LZAI9mOPFdAtnIz/8f38DBZQVhT7 +upeG7rRJA1TuG1l/MDoCgoYhrv7wFfLfToPmmcW6NfcgkIw47XXP4S73BDD7Ua2O +giRAyn0pXdXZ92Vk/KqfdLh9kl3ShCngE+qK99CrxK7vFcXCifJ7tjtJmGHzTnKR +N4xJkunI7Cqg90lufA0kxmts8jgvynAF5X/fxisrgIDV2m/LQLvYG/AkyRDIRAJ+ +LtOYqqIN8SvQ2vqOHP9U6OFKbt2o1ni1N6WsZNUUI8cOpevhCTjXwHxgpV2Yj4wC +1dxWqPNNWKkL1HxkdAEy8t8PSoqpAqKiHYR3wvHMl700GXRd4nQ+dSf3r7/ufA5t +VIimVuImrTESPB5BeW0X6hNeH/Vcn0lZo7Ivo0LD+qh+v6WfSMlgYmIK371F3uNC +tVGW/cT1Gpm4UqJEzS1hjBWPgdVdotSQPYxuQGHDWV3Y2eH2dEcieXR92sqjbzcV +NvAsGnE8EXbfXRo+VGN4a2V+Hw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIHqTCCBZGgAwIBAgIQYwaGp8U3ZaVDkKhqWMzUMjANBgkqhkiG9w0BAQUFADCB +jzELMAkGA1UEBhMCTFYxNTAzBgNVBAoTLFZBUyBMYXR2aWphcyBQYXN0cyAtIFZp +ZW4ucmVnLk5yLjQwMDAzMDUyNzkwMSMwIQYDVQQLExpTZXJ0aWZpa2FjaWphcyBw +YWthbHBvanVtaTEkMCIGA1UEAxMbVkFTIExhdHZpamFzIFBhc3RzIFNTSShSQ0Ep +MB4XDTA2MDkxMzA5MjIxMFoXDTI0MDkxMzA5Mjc1N1owgY8xCzAJBgNVBAYTAkxW +MTUwMwYDVQQKEyxWQVMgTGF0dmlqYXMgUGFzdHMgLSBWaWVuLnJlZy5Oci40MDAw +MzA1Mjc5MDEjMCEGA1UECxMaU2VydGlmaWthY2lqYXMgcGFrYWxwb2p1bWkxJDAi +BgNVBAMTG1ZBUyBMYXR2aWphcyBQYXN0cyBTU0koUkNBKTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAJu4+f1hVS9PpKUUtS6OuSSPrPuxVD9A/0/F5YZo +e1OT+zWCNahQLpRSoNuDPnXaFXCsCc/ugkmtNkm5tHGLtAChQgbKCApjl7YI/O60 +3Jh4GYLJ+H9kPqrJ/rGN67Bk9bzzxD46kOpOjj8bGbxqg8ORPGxV+wpSwOjhXXeF +M8VJ3+xqv79sN/6OSaIVGM6LjmseOKMwb4iBfnJWRBrEejkP9sSPltSy6wBOXN67 +5zu35iQFk2tN5pFEv+6YG8eFGxFBeyI2p74+6Ho33BjekJ2PzbLXmj/iF39bDOHv +P2Y9biTksM7DDIhslNo4JXxSOeNzFLMARWOaDEJAXgTG93JkzsluM7Pk020klTeT +fvIAXRmLH/NDc6ifRdIGqey0Qrv67gzHTz9RH9Gv0KwYf4eBIv6p3QeWbXz4TtlN +OlBp1UF+xdp02I5z5X6D4cMZgbe9v0COvi6aogyqTgIuuyrhCF0xA8msJ7Cv3NXI +FH1AnVWJIfmQzNTJYEFzq+jN2DpVOQqCmf6b9fU8HJHLwPpGVK4h/CqsXHveepdx +/WxrzUiapNuBfBg3L5B9YZS9F8lctlQWd8oJSqrpvE+UdQFaVryS0o+515feVnQB +9xZxSbH1GEaZQe5i4bMsZXVpKXJDA/ibH/o49J7sQBCOrJfVsDO+nxjcLfdBeFRK +YkTnAgMBAAGjggH9MIIB+TAOBgNVHQ8BAf8EBAMCAQYwGAYIKwYBBQUHAQMEDDAK +MAgGBgQAjkYBATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTMw/Vm/3OsOFqW +GyGJuIFMH8teJTAQBgkrBgEEAYI3FQEEAwIBADCCAYkGA1UdIASCAYAwggF8MIIB +eAYLKwYBBAGBxFkBAQIwggFnMIIBOAYIKwYBBQUHAgIwggEqHoIBJgBTAGkAcwAg +AGkAcgAgAHMAZQByAHQAaQBmAGkAawBhAHQAcwAsACAAawBvACAAaQB6AGQAZQB2 +AGkAcwAgAFYAQQBTACAATABhAHQAdgBpAGoAYQBzACAAUABhAHMAdABzACwAIABu +AG8AZAByAG8AcwBpAG4AbwB0ACAAYQB0AGIAaQBsAHMAdABpAGIAdQAgAEUAbABl +AGsAdAByAG8AbgBpAHMAawBvACAAZABvAGsAdQBtAGUAbgB0AHUAIABsAGkAawB1 +AG0AYQBtACAAdQBuACAARQBpAHIAbwBwAGEAcwAgAFAAYQByAGwAYQBtAGUAbgB0 +AGEAIABkAGkAcgBlAGsAdABpAHYAYQBpACAAMQA5ADkAOQAvADkAMwAvAEUASzAp +BggrBgEFBQcCARYdaHR0cDovL3d3dy5lLW1lLmx2L3JlcG9zaXRvcnkwDQYJKoZI +hvcNAQEFBQADggIBAB8oSjWQIWNoCi94r6MegiaXoz8nGdJLo0J6BhNlW8EEy+t9 +fO+U8vGJ9bffUgIhadLqljTloM+XuJxVDhCFoxReLAX4tTp28/l6uN62DCdp8suU +kQsdudWOb5kvzfIZVjk6SFbwAf+Cdbay/dHU9fJjV0xNoX7MELoEae/0FPyzlx9F +7m9KKH/Rxie8x6Opa3vtghNvq94P+3HrXBEaqSzQMJ/8NjdW75XpurcTtq6fAmGt +nuxrBG82nw+Z98LJyEwouSjUIdeeVNXAzvSO5FWUe48kxjj8q3qkVnc9qEXvZJKk +0Ep+u3OL9A1Sc7g6SF5DgNOpcHdi/8coHHMeQ+YnJFtJueY2pI79xS0veqV5EnrX +IbIlbcgPosNhS+VI4le6n/KKId3bZPDaGd/OwJuAOcJ3d2MVU3KE+qSPBzeGIX1Q ++j1qN9uRDjez/c4Lynth0Jx0nH04aG3pex3W8Sq07ztgUncF5gLCX4xbvPB9t3PH +kWuyKrNjozTVq60lcUf/Gj56to2VdsPups0DCWzuRWeYz5lIdsHOinSaaFIBNCLI +7eIUC4S9bhCMsXKbvugI11fVf+q0AT1O5OLoZ+eMfunnQhHvlUbIkda+JxeAGTSY +58bfHvwhX56GPbx+8Jy9cp70R4JbcWfz+txUTKhc2FnH0AcOEzMnvPRp8Gsh +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIIBhDCeat3PfIwDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UE +BhMCQ0gxEjAQBgNVBAoTCVN3aXNzU2lnbjEyMDAGA1UEAxMpU3dpc3NTaWduIENB +IChSU0EgSUsgTWF5IDYgMTk5OSAxODowMDo1OCkxHzAdBgkqhkiG9w0BCQEWEGNh +QFN3aXNzU2lnbi5jb20wHhcNMDAxMTI2MjMyNzQxWhcNMzExMTI2MjMyNzQxWjB2 +MQswCQYDVQQGEwJDSDESMBAGA1UEChMJU3dpc3NTaWduMTIwMAYDVQQDEylTd2lz +c1NpZ24gQ0EgKFJTQSBJSyBNYXkgNiAxOTk5IDE4OjAwOjU4KTEfMB0GCSqGSIb3 +DQEJARYQY2FAU3dpc3NTaWduLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAKw5fjnmNneLQlUCQG8jQLwwfbrOZoUwNX8cbNqhxK03/xUloFVgAt+S +Te2RxNXaCAXLBPn5ZST35TLV57aLmbHCtifv3YZqaaQGvjedltIBMJihJhZ+h3LY +SKsUb+xEJ3x5ZUf8jP+Q1g57y1s8SnBFWN/ni5NkF1Y1y31VwOi9wiOf/VISL+uu +SC4i1CP1Kbz3BDs6Hht1GpRYCbJ/K0bc9oJSpWpT5PGONsGIawqMbJuyoDghsXQ1 +pbn2e8K64BSscGZVZTNooSGgNiHmACNJBYXiWVWrwXPF4l6SddmC3Rj0aKXjgECc +FkHLDQcsM5JsK2ZLryTDUsQFbxVP2ikCAwEAAaNHMEUwCwYDVR0PBAQDAgEGMAwG +A1UdEwQFMAMBAf8wHQYDVR0OBBYEFJbXcc05KtT8iLGKq1N4ae+PR34WMAkGA1Ud +IwQCMAAwDQYJKoZIhvcNAQEFBQADggEBAKMy6W8HvZdS1fBpEUzl6Lvw50bgE1Xc +HU1JypSBG9mhdcXZo5AlPB4sCvx9Dmfwhyrdsshc0TP2V3Vh6eQqnEF5qB4lVziT +Bko9mW6Ot+pPnwsy4SHpx3rw6jCYnOqfUcZjWqqqRrq/3P1waz+Mn4cLMVEg3Xaz +qYov/khvSqS0JniwjRlo2H6f/1oVUKZvP+dUhpQepfZrOqMAWZW4otp6FolyQyeU +NN6UCRNiUKl5vTijbKwUUwfER/1Vci3M1/O1QCfttQ4vRN4Buc0xqYtGL3cd5WiO +vWzyhlTzAI6VUdNkQhhHJSAyTpj6dmXDRzrryoFGa2PjgESxz7XBaSI= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx +MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg +Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ +iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa +/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ +jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI +HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 +sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w +gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw +KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG +AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L +URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO +H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm +I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY +iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB +kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw +IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD +VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu +dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 +E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ +D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK +4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq +lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW +bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB +o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT +MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js +LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr +BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB +AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft +Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj +j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH +KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv +2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 +mfnGV/TJVTl4uix5yaaIK/QI +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM +V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB +4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr +H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd +8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv +vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT +mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe +btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc +T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt +WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ +c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A +4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD +VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG +CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 +aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw +czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G +A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg +Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 +7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem +d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd ++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B +4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN +t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x +DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 +k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s +zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j +Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT +mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK +4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzET +MBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UE +AxMIQ0EgRGlzaWcwHhcNMDYwMzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQsw +CQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcg +YS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgmGErE +Nx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnX +mjxUizkDPw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYD +XcDtab86wYqg6I7ZuUUohwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhW +S8+2rT+MitcE5eN4TPWGqvWP+j1scaMtymfraHtuM6kMgiioTGohQBUgDCZbg8Kp +FhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8wgfwwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0PAQH/BAQD +AgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cu +ZGlzaWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5z +ay9jYS9jcmwvY2FfZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2sv +Y2EvY3JsL2NhX2Rpc2lnLmNybDAaBgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEw +DQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59tWDYcPQuBDRIrRhCA/ec8J9B6 +yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3mkkp7M5+cTxq +EEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ +CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeB +EicTXxChds6KezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFN +PGO+I++MzVpQuGhU+QqZMxEA4Z7CRneC9VkGjCFMhwnN5ag= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw +MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD +VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul +CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n +tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl +dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch +PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC ++Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O +BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk +ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB +IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X +7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz +43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY +eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl +pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA +WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJE +SzEMMAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEw +ODM5MzBaFw0zNzAyMTEwOTA5MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNU +REMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuHnEz9pPPEXyG9VhDr +2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0zY0s +2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItU +GBxIYXvViGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKj +dGqPqcNiKXEx5TukYBdedObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+r +TpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/ +BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB5DCB4TCB3gYIKoFQgSkB +AQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5kay9yZXBv +c2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRl +ciBmcmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEu +MS4xLiBDZXJ0aWZpY2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIg +T0lEIDEuMi4yMDguMTY5LjEuMS4xLjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1Ud +HwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEMMAoGA1UEChMDVERDMRQwEgYD +VQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYmaHR0cDovL2Ny +bC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy +MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZ +J2cdUBVLc647+RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqG +SIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACrom +JkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4A9G28kNBKWKnctj7fAXmMXAnVBhO +inxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYscA+UYyAFMP8uXBV2Y +caaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9AOoB +mbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQ +YqbsFbS1AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9 +BKNDLdr8C2LqL19iUw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUx @@ -2679,6 +2948,350 @@ VCHnpgu0mfVRQdzNo0ci2ccBgcTcR08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY macqaJVmlaut74nLYKkGEsaUR+ko -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIICmDCCAgGgAwIBAgIBDjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNFQ0ExFDASBgNVBAMT +C0VDQSBSb290IENBMB4XDTA0MDYxNDEwMjAwOVoXDTQwMDYxNDEwMjAwOVowSzEL +MAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMD +RUNBMRQwEgYDVQQDEwtFQ0EgUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEArkr2eXIS6oAKIpDkOlcQZdMGdncoygCEIU+ktqY3of5SVVXU7/it7kJ1 +EUzR4ii2vthQtbww9aAnpQxcEmXZk8eEyiGEPy+cCQMllBY+efOtKgjbQNDZ3lB9 +19qzUJwBl2BMxslU1XsJQw9SK10lPbQm4asa8E8e5zTUknZBWnECAwEAAaOBizCB +iDAfBgNVHSMEGDAWgBT2uAQnDlYW2blj2f2hVGVBoAhILzAdBgNVHQ4EFgQU9rgE +Jw5WFtm5Y9n9oVRlQaAISC8wDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB +Af8wJQYDVR0gBB4wHDAMBgpghkgBZQMCAQwBMAwGCmCGSAFlAwIBDAIwDQYJKoZI +hvcNAQEFBQADgYEAHh0EQY2cZ209aBb5q0wW1ER0dc4OGzsLyqjHfaQ4TEaMmUwL +AJRta/c4KVWLiwbODsvgJk+CaWmSL03gRW/ciVb/qDV7qh9Pyd1cOlanZTAnPog2 +i82yL3i2fK9DCC84uoxEQbgqK2jx9bIjFTwlAqITk9fGAm5mdT84IEwq1Gw= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCB +rjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0BgNVBAMTLVVUTi1VU0VSRmlyc3Qt +Q2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05OTA3MDkxNzI4NTBa +Fw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAV +BgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l +dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UE +AxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3B +YHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9 +hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8om+rWV6l +L8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLm +SGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM +1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws +6wIDAQABo4G5MIG2MAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNVHR8EUTBPME2gS6BJhkdodHRw +Oi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGllbnRBdXRoZW50 +aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH +AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u +7mFVbwQ+zznexRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0 +xtcgBEXkzYABurorbs6q15L+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQ +rfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarVNZ1yQAOJujEdxRBoUp7fooXFXAim +eOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZw7JHpsIyYdfHb0gk +USeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDIjCCAougAwIBAgIQNKT/9jCvTKU8MxdCoZRmdTANBgkqhkiG9w0BAQUFADCB +xDELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJ +Q2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UE +CxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhh +d3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0 +ZS5jb20wHhcNOTYwODAxMDAwMDAwWhcNMjEwMTAxMjM1OTU5WjCBxDELMAkGA1UE +BhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3du +MR0wGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlm +aWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZl +ciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8w +DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl +/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF +/rFrKbYvScg71CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982 +OsK1ZiIS1ocNAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEF +BQADgYEAvkBpQW/G28GnvwfAReTQtUMeTJUzNelewj4o9qgNUNX/4gwP/FACjq6R +ua00io2fJ3GqGcxL6ATK1BdrEhrWxl/WzV7/iXa/2EjYWb0IiokdV81FHlK6EpqE ++hiJX+j5MDVqAWC5mYCDhQpu2vTJj15zLTFKY6B08h+LItIpPus= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBlcnNvbmFsIEJhc2lj +IENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNpY0B0aGF3dGUuY29tMB4X +DTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgcsxCzAJBgNVBAYTAlpBMRUw +EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE +ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy +dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBD +QTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53 +dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdK +wPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7 +G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQF +AAOBgQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7 +c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95B21P +9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP +bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2 +MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft +ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC +206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci +KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2 +JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9 +BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e +Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B +PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67 +Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq +Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ +o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3 ++L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj +YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj +FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn +xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2 +LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc +obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8 +CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe +IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA +DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F +AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX +Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb +AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl +Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw +RY8mkaKO/qk= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMx +IDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxs +cyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9v +dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcxMjEzMTcwNzU0WhcNMjIxMjE0 +MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdl +bGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQD +DC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+r +WxxTkqxtnt3CxC5FlAM1iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjU +Dk/41itMpBb570OYj7OeUt9tkTmPOL13i0Nj67eT/DBMHAGTthP796EfvyXhdDcs +HqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8bJVhHlfXBIEyg1J55oNj +z7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiBK0HmOFaf +SZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/Slwxl +AgMBAAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqG +KGh0dHA6Ly9jcmwucGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0P +AQH/BAQDAgHGMB0GA1UdDgQWBBQmlRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0j +BIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGBi6SBiDCBhTELMAkGA1UEBhMC +VVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNX +ZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEB +ALkVsUSRzCPIK0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd +/ZDJPHV3V3p9+N701NX3leZ0bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pB +A4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSljqHyita04pO2t/caaH/+Xc/77szWn +k4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+esE2fDbbFwRnzVlhE9 +iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJtylv +2G0xffX8oRAHh84vWdw+WNs= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgIQMDAwMDk3Mzc1NzM4NjAwMDANBgkqhkiG9w0BAQUFADBV +MQswCQYDVQQGEwJGUjETMBEGA1UEChMKQ2VydGlOb21pczEcMBoGA1UECxMTQUMg +UmFjaW5lIC0gUm9vdCBDQTETMBEGA1UEAxMKQ2VydGlOb21pczAeFw0wMDExMDkw +MDAwMDBaFw0xMjExMDkwMDAwMDBaMFUxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpD +ZXJ0aU5vbWlzMRwwGgYDVQQLExNBQyBSYWNpbmUgLSBSb290IENBMRMwEQYDVQQD +EwpDZXJ0aU5vbWlzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8SWb +4mS5RXB3ENSIcfrEzCj/TRUQuT1tMCU0YUfXFSgcPdWglIzCv3kvh07QoB+8xMl+ +fQHvSSduAxnNewz0GBY9rApCPKlP6CcnJr74OSVZIiWt9wLfl4wwhNhZOiikIpZp +EdOXWqRc84P5cUlN3Lwmr1sjCWmHfTSS4cAKxfDbFLfE61etosyoFZUTQbIhb1Bf +JL5xRXAUZudQiU42n/yAoSUrN4FLUfPQNlOe1AB81pIgX8g2ojwxDjfgqSs1JmBF +uLKJ45uVLEenQBPmQCGjL3maV86IRmR3a9UGlgvKAk0NBdh8mrQyQvcUlLBIQBCm +l7wppt6maQHUNEPQSwIDAQABoz8wPTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQU+F4ho6ijFeb4tRG7/kIEXU2OgnowDQYJKoZIhvcNAQEF +BQADggEBACe9FJayK6bXkJQrilBFMh75QPdFOks9PJuo86OMUlBDZGYFTCh9Arex +N3KYCnAEzazYIALwr7eASJJDIQMu1Q+pkx/7ACde4kP47F27M2rm+v5HnGooCLz2 +s7Fe/WUycTQqgwF5lNp03m1ce/TvovgkEZeVN5wM/7+SsZLJGDigXGeq48j2g2hn +8OckX9Ciyo0U3/1IVeigNBisiaOlsHSZOEPBZQRiZULob+NVbXVPo8nM1OyP3aHI +LQex1yYcCr9m93nOiZyKkur3Uedf1yMTBe+fflnPFKGYnVqvTGXCKVdHzQBfpILA +AuaC+5ykZhSiSMf8nmL2oPMcLO7YQw4= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL +ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx +MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc +MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ +AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH +iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj +vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA +0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB +OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ +BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E +FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 +GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW +zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 +1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE +f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F +jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN +ZetX2fNXlrtIzYE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGUTCCBTmgAwIBAgIEPLVPQDANBgkqhkiG9w0BAQUFADBmMRIwEAYDVQQKEwli +ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEzMDEGA1UEAxMq +YmVUUlVTVGVkIFJvb3QgQ0EgLSBFbnRydXN0IEltcGxlbWVudGF0aW9uMB4XDTAy +MDQxMTA4MjQyN1oXDTIyMDQxMTA4NTQyN1owZjESMBAGA1UEChMJYmVUUlVTVGVk +MRswGQYDVQQLExJiZVRSVVNUZWQgUm9vdCBDQXMxMzAxBgNVBAMTKmJlVFJVU1Rl +ZCBSb290IENBIC0gRW50cnVzdCBJbXBsZW1lbnRhdGlvbjCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALr0RAOqEmq1Q+xVkrYwfTVXDNvzDSduTPdQqJtO +K2/b9a0cS12zqcH+e0TrW6MFDR/FNCswACnxeECypP869AGIF37m1CbTukzqMvtD +d5eHI8XbQ6P1KqNRXuE70mVpflUVm3rnafdE4Fe1FehmYA8NA/uCjqPoEXtsvsdj +DheT389Lrm5zdeDzqrmkwAkbhepxKYhBMvnwKg5sCfJ0a2ZsUhMfGLzUPvfYbiCe +yv78IZTuEyhL11xeDGbu6bsPwTSxfwh28z0mcMmLJR1iJAzqHHVOwBLkuhMdMCkt +VjMFu5dZfsZJT4nXLySotohAtWSSU1Yk5KKghbNekLQSM80CAwEAAaOCAwUwggMB +MIIBtwYDVR0gBIIBrjCCAaowggGmBg8rBgEEAbE+AAACCSiDkTEwggGRMIIBSQYI +KwYBBQUHAgIwggE7GoIBN1JlbGlhbmNlIG9uIG9yIHVzZSBvZiB0aGlzIENlcnRp +ZmljYXRlIGNyZWF0ZXMgYW4gYWNrbm93bGVkZ21lbnQgYW5kIGFjY2VwdGFuY2Ug +b2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0 +aW9ucyBvZiB1c2UsIHRoZSBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dCBhbmQgdGhlIFJlbHlpbmcgUGFydHkgQWdyZWVtZW50LCB3aGljaCBjYW4gYmUg +Zm91bmQgYXQgdGhlIGJlVFJVU1RlZCB3ZWIgc2l0ZSwgaHR0cHM6Ly93d3cuYmV0 +cnVzdGVkLmNvbS9wcm9kdWN0c19zZXJ2aWNlcy9pbmRleC5odG1sMEIGCCsGAQUF +BwIBFjZodHRwczovL3d3dy5iZXRydXN0ZWQuY29tL3Byb2R1Y3RzX3NlcnZpY2Vz +L2luZGV4Lmh0bWwwEQYJYIZIAYb4QgEBBAQDAgAHMIGJBgNVHR8EgYEwfzB9oHug +eaR3MHUxEjAQBgNVBAoTCWJlVFJVU1RlZDEbMBkGA1UECxMSYmVUUlVTVGVkIFJv +b3QgQ0FzMTMwMQYDVQQDEypiZVRSVVNUZWQgUm9vdCBDQSAtIEVudHJ1c3QgSW1w +bGVtZW50YXRpb24xDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMjA0MTEw +ODI0MjdagQ8yMDIyMDQxMTA4NTQyN1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaA +FH1w5a44iwY/qhwaj/nPJDCqhIQWMB0GA1UdDgQWBBR9cOWuOIsGP6ocGo/5zyQw +qoSEFjAMBgNVHRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIE +kDANBgkqhkiG9w0BAQUFAAOCAQEAKrgXzh8QlOu4mre5X+za95IkrNySO8cgjfKZ +5V04ocI07cUTWVwFtStPYZuR+0H8/NU8TZh2BvWBfevdkObRVlTa4y0MnxEylCIB +evZsLHRnBMylj44ss0O1lKLQfelifwa+JwGDnjr9iu6YQ0pr17WXOzq/T220Y/oz +ADQuLW2WyXvKmWO6vvT2MKAtmJbpVkQFqUSjYRDrgqFnXbxdJ3Wqiig2KjiS2d2k +XgClzMx8KSreKJCrt+G2/30lC0DYqjSjLd4H61/OCt3Kfjp9JsFiaDrmLzfzgYYh +xKlkqu9FNtEaZnz46TfW1mG+oq1I59/mdP7TbX3SJdysYlep9w== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEuzCCA6OgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzET +MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwHhcNMDYwNDI1MjE0 +MDM2WhcNMzUwMjA5MjE0MDM2WjBiMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBw +bGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx +FjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDkkakJH5HbHkdQ6wXtXnmELes2oldMVeyLGYne+Uts9QerIjAC6Bg+ ++FAJ039BqJj50cpmnCRrEdCju+QbKsMflZ56DKRHi1vUFjczy8QPTc4UadHJGXL1 +XQ7Vf1+b8iUDulWPTV0N8WQ1IxVLFVkds5T39pyez1C6wVhQZ48ItCD3y6wsIG9w +tj8BMIy3Q88PnT3zK0koGsj+zrW5DtleHNbLPbU6rfQPDgCSC7EhFi501TwN22IW +q6NxkkdTVcGvL0Gz+PvjcM3mo0xFfh9Ma1CWQYnEdGILEINBhzOKgbEwWOxaBDKM +aLOPHd5lc/9nXmW8Sdh2nzMUZaF3lMktAgMBAAGjggF6MIIBdjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUK9BpR5R2Cf70a40uQKb3 +R01/CF4wHwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wggERBgNVHSAE +ggEIMIIBBDCCAQAGCSqGSIb3Y2QFATCB8jAqBggrBgEFBQcCARYeaHR0cHM6Ly93 +d3cuYXBwbGUuY29tL2FwcGxlY2EvMIHDBggrBgEFBQcCAjCBthqBs1JlbGlhbmNl +IG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0 +YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBj +b25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZp +Y2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMA0GCSqGSIb3DQEBBQUAA4IBAQBc +NplMLXi37Yyb3PN3m/J20ncwT8EfhYOFG5k9RzfyqZtAjizUsZAS2L70c5vu0mQP +y3lPNNiiPvl4/2vIB+x9OYOLUyDTOMSxv5pPCmv/K/xZpwUJfBdAVhEedNO3iyM7 +R6PVbyTi69G3cN8PReEnyvFteO3ntRcXqNx+IjXKJdXZD9Zr1KIkIxH3oayPc4Fg +xhtbCS+SsvhESPBgOJ4V9T0mZyCKM2r3DYLP3uujL/lTaltkwGMzd/c6ByxW69oP +IQ7aunMZT7XZNn/Bh1XZp5m5MkL72NVxnn6hUrcbvZNCJBIqxw8dtk2cXmPIS4AX +UKqK1drk/NAJBzewdXUh +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCB +lTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAbBgNVBAMTFFVUTi1VU0VSRmlyc3Qt +T2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAzNlowgZUxCzAJBgNV +BAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxHjAc +BgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3 +dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicP +HxzfOpuCaDDASmEd8S8O+r5596Uj71VRloTN2+O5bj4x2AogZ8f02b+U60cEPgLO +KqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQw5ujm9M89RKZd7G3CeBo +5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vulBe3/IW+ +pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehb +kkj7RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUC +AwEAAaOBrzCBrDALBgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQU2u1kdBScFDyr3ZmpvVsoTYs8ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov +L2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0LmNybDApBgNV +HSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQwDQYJKoZIhvcN +AQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw +NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXB +mMiKVl0+7kNOPmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU +4U3GDZlDAQ0Slox4nb9QorFEqmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK5 +81OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCGhU3IfdeLA/5u1fedFqySLKAj5ZyR +Uh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm +SVBTIENBIENMQVNFQTMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT +JklQUyBDQSBDTEFTRUEzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI +hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjI5MDEwNzUwWhcNMjUxMjI3 +MDEwNzUwWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO6AAPYaZC6tasiDsYun7o/ZttvN +G7uGBiJ2MwwSbUhWYdLcgiViL5/SaTBlA0IjWLxH3GvWdV0XPOH/8lhneaDBgbHU +VqLyjRGZ/fZ98cfEXgIqmuJKtROKAP2Md4bm15T1IHUuDky/dMQ/gT6DtKM4Ninn +6Cr1jIhBqoCm42zvAgMBAAGjggRTMIIETzAdBgNVHQ4EFgQUHp9XUEe2YZM50yz8 +2l09BXW3mQIwggFGBgNVHSMEggE9MIIBOYAUHp9XUEe2YZM50yz82l09BXW3mQKh +ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC +AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF +BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB +BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg +hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud +EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0VBMyBD +QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cDovL3d3dy5pcHMuZXMvMCkGCWCG +SAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyLzA7BglghkgBhvhC +AQQELhYsaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VBMy5j +cmwwQAYJYIZIAYb4QgEDBDMWMWh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2 +b2NhdGlvbkNMQVNFQTMuaHRtbD8wPQYJYIZIAYb4QgEHBDAWLmh0dHA6Ly93d3cu +aXBzLmVzL2lwczIwMDIvcmVuZXdhbENMQVNFQTMuaHRtbD8wOwYJYIZIAYb4QgEI +BC4WLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VBMy5odG1s +MHUGA1UdHwRuMGwwMqAwoC6GLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvaXBz +MjAwMkNMQVNFQTMuY3JsMDagNKAyhjBodHRwOi8vd3d3YmFjay5pcHMuZXMvaXBz +MjAwMi9pcHMyMDAyQ0xBU0VBMy5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF +BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAEo9IEca +2on0eisxeewBwMwB9dbB/MjD81ACUZBYKp/nNQlbMAqBACVHr9QPDp5gJqiVp4MI +3y2s6Q73nMify5NF8bpqxmdRSmlPa/59Cy9SKcJQrSRE7SOzSMtEQMEDlQwKeAYS +AfWRMS1Jjbs/RU4s4OjNtckUFQzjB4ObJnXv +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV @@ -2712,110 +3325,1084 @@ ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y 8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x -GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv -b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV -BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W -YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM -V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB -4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr -H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd -8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv -vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT -mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe -btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc -T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt -WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ -c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A -4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD -VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG -CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 -aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 -aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu -dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw -czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G -A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg -Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 -7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem -d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd -+LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B -4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN -t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x -DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 -k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s -zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j -Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT -mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK -4SVhM7JZG+Ju1zdXtg2pEto= +MIIDPDCCAqWgAwIBAgIQEj3w59oqIkekOIngiu7JZzANBgkqhkiG9w0BAQUFADCB +0TELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJ +Q2FwZSBUb3duMRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3Rl +IFBlcnNvbmFsIEZyZWVtYWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1m +cmVlbWFpbEB0aGF3dGUuY29tMB4XDTk2MDEwMTAwMDAwMFoXDTIxMDEwMTIzNTk1 +OVowgdExCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNV +BAcTCUNhcGUgVG93bjEaMBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNV +BAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1Ro +YXd0ZSBQZXJzb25hbCBGcmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29u +YWwtZnJlZW1haWxAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC +gYEA1GnX1LCUZFtx6UfYDFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Z +hx2G6qPduc6WZBrCFG5ErHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56 +fAylS1V/Bhkpf56aJtVquzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYD +VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAemGDU5fJUYLA9GoFkR/db +o9lvwykLp9KpgUn2w22FFChFRAH0cVyVLhQPGivRqWvBX2c9FvFyIK++FsoOMF/J +y6WTLMNnVB5yIoojdmyUHVFSbJ3E4EcC18y/8IB7GG4l3GJh1qb+wR1/2bP9jVxF +EFrGZWSa6yz1A0/WSGL7Lg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz -MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv -cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz -Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO -0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao -wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj -7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS -8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT -BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg -JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC -NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 -6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ -3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm -D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS -CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR -3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y +YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua +kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL +QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp +6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG +yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i +QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO +tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu +QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ +Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u +olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 +x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx -MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg -Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ -iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa -/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ -jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI -HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 -sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w -gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw -KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG -AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L -URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO -H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm -I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY -iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc -f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm +MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx +MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 +dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl +cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 +DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 +yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX +L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj +EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG +7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e +QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ +qdq5snUb9kLy78fyGPmJvKP/iiMucEc= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl -MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp -U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw -NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE -ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp -ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 -DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf -8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN -+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 -X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa -K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA -1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G -A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR -zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 -YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD -bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w -DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 -L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D -eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl -xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp -VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY -WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +MIIEUDCCA7mgAwIBAgIJAN4ppNGwj6yIMA0GCSqGSIb3DQEBBAUAMIHMMQswCQYD +VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j +aXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5jLjEpMCcGA1UECxMgTGluZGVu +IExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAnBgNVBAMTIExpbmRlbiBMYWIg +Q2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZIhvcNAQkBFhBjYUBsaW5kZW5s +YWIuY29tMB4XDTA1MDQyMTAyNDAzMVoXDTI1MDQxNjAyNDAzMVowgcwxCzAJBgNV +BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp +c2NvMRkwFwYDVQQKExBMaW5kZW4gTGFiLCBJbmMuMSkwJwYDVQQLEyBMaW5kZW4g +TGFiIENlcnRpZmljYXRlIEF1dGhvcml0eTEpMCcGA1UEAxMgTGluZGVuIExhYiBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgkqhkiG9w0BCQEWEGNhQGxpbmRlbmxh +Yi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKXh1MThucdTbMg9bYBO +rAm8yWns32YojB0PRfbq8rUjepEhTm3/13s0u399Uc202v4ejcGhkIDWJZd2NZMF +oKrhmRfxGHSKPCuFaXC3jh0lRECj7k8FoPkcmaPjSyodrDFDUUuv+C06oYJoI+rk +8REyal9NwgHvqCzOrZtiTXAdAgMBAAGjggE2MIIBMjAdBgNVHQ4EFgQUO1zK2e1f +1wO1fHAjq6DTJobKDrcwggEBBgNVHSMEgfkwgfaAFDtcytntX9cDtXxwI6ug0yaG +yg63oYHSpIHPMIHMMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW +MBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5j +LjEpMCcGA1UECxMgTGluZGVuIExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAn +BgNVBAMTIExpbmRlbiBMYWIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZI +hvcNAQkBFhBjYUBsaW5kZW5sYWIuY29tggkA3imk0bCPrIgwDAYDVR0TBAUwAwEB +/zANBgkqhkiG9w0BAQQFAAOBgQA/ZkgfvwHYqk1UIAKZS3kMCxz0HvYuEQtviwnu +xA39CIJ65Zozs28Eg1aV9/Y+Of7TnWhW+U3J3/wD/GghaAGiKK6vMn9gJBIdBX/9 +e6ef37VGyiOEFFjnUIbuk0RWty0orN76q/lI/xjCi15XSA/VSq2j4vmnwfZcPTDu +glmQ1A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c +JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP +mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ +wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 +VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ +AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB +AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun +pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC +dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf +fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm +NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx +H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEuDCCA6CgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBtDELMAkGA1UEBhMCQlIx +EzARBgNVBAoTCklDUC1CcmFzaWwxPTA7BgNVBAsTNEluc3RpdHV0byBOYWNpb25h +bCBkZSBUZWNub2xvZ2lhIGRhIEluZm9ybWFjYW8gLSBJVEkxETAPBgNVBAcTCEJy +YXNpbGlhMQswCQYDVQQIEwJERjExMC8GA1UEAxMoQXV0b3JpZGFkZSBDZXJ0aWZp +Y2Fkb3JhIFJhaXogQnJhc2lsZWlyYTAeFw0wMTExMzAxMjU4MDBaFw0xMTExMzAy +MzU5MDBaMIG0MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE9MDsG +A1UECxM0SW5zdGl0dXRvIE5hY2lvbmFsIGRlIFRlY25vbG9naWEgZGEgSW5mb3Jt +YWNhbyAtIElUSTERMA8GA1UEBxMIQnJhc2lsaWExCzAJBgNVBAgTAkRGMTEwLwYD +VQQDEyhBdXRvcmlkYWRlIENlcnRpZmljYWRvcmEgUmFpeiBCcmFzaWxlaXJhMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwPMudwX/hvm+Uh2b/lQAcHVA +isamaLkWdkwP9/S/tOKIgRrL6Oy+ZIGlOUdd6uYtk9Ma/3pUpgcfNAj0vYm5gsyj +Qo9emsc+x6m4VWwk9iqMZSCK5EQkAq/Ut4n7KuLE1+gdftwdIgxfUsPt4CyNrY50 +QV57KM2UT8x5rrmzEjr7TICGpSUAl2gVqe6xaii+bmYR1QrmWaBSAG59LrkrjrYt +bRhFboUDe1DK+6T8s5L6k8c8okpbHpa9veMztDVC9sPJ60MWXh6anVKo1UcLcbUR +yEeNvZneVRKAAU6ouwdjDvwlsaKydFKwed0ToQ47bmUKgcm+wV3eTRk36UOnTwID +AQABo4HSMIHPME4GA1UdIARHMEUwQwYFYEwBAQAwOjA4BggrBgEFBQcCARYsaHR0 +cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0RQQ2FjcmFpei5wZGYwPQYDVR0f +BDYwNDAyoDCgLoYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0xDUmFj +cmFpei5jcmwwHQYDVR0OBBYEFIr68VeEERM1kEL6V0lUaQ2kxPA3MA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAZA5c1 +U/hgIh6OcgLAfiJgFWpvmDZWqlV30/bHFpj8iBobJSm5uDpt7TirYh1Uxe3fQaGl +YjJe+9zd+izPRbBqXPVQA34EXcwk4qpWuf1hHriWfdrx8AcqSqr6CuQFwSr75Fos +SzlwDADa70mT7wZjAmQhnZx2xJ6wfWlT9VQfS//JYeIc7Fue2JNLd00UOSMMaiK/ +t79enKNHEA2fupH3vEigf5Eh4bVAN5VohrTm6MY53x7XQZZr1ME7a55lFEnSeT0u +mlOAjR2mAbvSM5X5oSZNrmetdzyTj2flCM8CC7MLab0kkdngRIlUBGHF1/S5nmPb +K+9A46sd33oqK8n8 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJKUDEO +MAwGA1UEChMFTEdQS0kxGjAYBgNVBAsTEUFwcGxpY2F0aW9uIENBIEcyMB4XDTA2 +MDMzMTE1MDAwMFoXDTE2MDMzMTE0NTk1OVowOTELMAkGA1UEBhMCSlAxDjAMBgNV +BAoTBUxHUEtJMRowGAYDVQQLExFBcHBsaWNhdGlvbiBDQSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBALk1xhD422jbB8RATLAdHjbcw0H2z1UVbQh/ +XMZoVeXnV/GWUebhTXgPbkAVcDtl/hHf59PWWDU74Z8C/JRSRi6znmCbAp7JgtL2 +464JT4REtmKbAFFouDqt7GTRMkvplESDtA7OIYlrsDbAmMZLnMI+W2AqCTErLatM +3rGg/VhWwoMdILzEhAmHe6iVl8YljoPgPpMN0cd9c6mo/BkAQC4iuHozQfV4/Vpx +54LZSIhc7KiFhy1tgIlnGmm+EMBaju2IfT5vLDhrN85H2KIxMN5+U2Vsi4ZTQSBs +vUilfq8AWlYSWIHR3IlZ+bXu+E2a2EQpi3mn9yKq6nxctBaIIA0CAwEAAaOBsjCB +rzAdBgNVHQ4EFgQUf7hdjsQYa8Z9zC7prs405xdd4KEwDgYDVR0PAQH/BAQDAgEG +MEwGA1UdHwRFMEMwQaA/oD2kOzA5MQswCQYDVQQGEwJKUDEOMAwGA1UEChMFTEdQ +S0kxGjAYBgNVBAsTEUFwcGxpY2F0aW9uIENBIEcyMA8GA1UdEwEB/wQFMAMBAf8w +HwYDVR0jBBgwFoAUf7hdjsQYa8Z9zC7prs405xdd4KEwDQYJKoZIhvcNAQEFBQAD +ggEBADzYczZABkhKVBn1J0g5JaVuQue2zRvLOTS3m+xPKr535MqE/B3rmyJA1fT7 +aIdy/Eddag5SSuO1XUjGIpbmM21tq/bN18skWoyoRZ4+YYJ9lNUF8Bo1X3EvLlS1 +QQXvhg1S75yYG/EsTDrR84bTjD56L4ZFjoMyJlu/U8oOUVbcmsJaMBkNp57Vqpsg +OWl4IfSXbdEOEUwu0xtasPmXeFwqj1Jl7kxCJcI3MA5tKzWUgwbor0U7BGanMLv5 +4CE7Y259RF06alPvERck/VSyWmxzViHJbC2XpEKzJ2EFIWNt6ii8TxpvQtyYq1XT +HhvAkj+bweY7F1bixJhDJe62ywA= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsx +CzAJBgNVBAYTAkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRp +ZmljYWNpw7NuIERpZ2l0YWwgLSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwa +QUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4wHhcNMDYxMTI3MjA0NjI5WhcNMzAw +NDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+U29jaWVkYWQgQ2Ft +ZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJhIFMu +QS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeG +qentLhM0R7LQcNzJPNCNyu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzL +fDe3fezTf3MZsGqy2IiKLUV0qPezuMDU2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQ +Y5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU34ojC2I+GdV75LaeHM/J4 +Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP2yYe68yQ +54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+b +MMCm8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48j +ilSH5L887uvDdUhfHjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++Ej +YfDIJss2yKHzMI+ko6Kh3VOz3vCaMh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/zt +A/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK5lw1omdMEWux+IBkAC1vImHF +rEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1bczwmPS9KvqfJ +pxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCB +lTCBkgYEVR0gADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFy +YS5jb20vZHBjLzBaBggrBgEFBQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW50 +7WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2UgcHVlZGVuIGVuY29udHJhciBlbiBs +YSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEfAygPU3zmpFmps4p6 +xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuXEpBc +unvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/ +Jre7Ir5v/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dp +ezy4ydV/NgIlqmjCMRW3MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42 +gzmRkBDI8ck1fj+404HGIGQatlDCIaR43NAvO2STdPCWkPHv+wlaNECW8DYSwaN0 +jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wkeZBWN7PGKX6jD/EpOe9+ +XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f/RWmnkJD +W2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/ +RL5hRqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35r +MDOhYil/SrnhLecUIw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxk +BYn8eNZcLCZDqQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy +NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y +LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ +TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y +TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 +LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW +I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw +nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBlcnNvbmFsIFByZW1p +dW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXByZW1pdW1AdGhhd3RlLmNv +bTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5NTlaMIHPMQswCQYDVQQGEwJa +QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY +BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u +IFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJl +bWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUu +Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0Vs +Bd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWI +Et12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYD +ZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH +b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVxeTBh +KXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1KzGJ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0f +zGVuDLDQVoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHi +TkVWaR94AoDa3EeRKbs2yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0G +CSqGSIb3DQEBBQUAA4GBAFgVKTk8d6PaXCUDfGD67gmZPCcQcMgMCeazh88K4hiW +NWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n0a3hUKw8fGJLj7qE1xIV +Gx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZRjXZ+Hxb +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJD +TjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2 +MDcwOTE0WhcNMjcwNDE2MDcwOTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMF +Q05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzDo+/hn7E7SIX1mlwh +IhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tizVHa6 +dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZO +V/kbZKKTVrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrC +GHn2emU1z5DrvTOTn1OrczvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gN +v7Sg2Ca+I19zN38m5pIEo3/PIKe38zrKy5nLAgMBAAGjczBxMBEGCWCGSAGG+EIB +AQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscCwQ7vptU7ETAPBgNVHRMB +Af8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991SlgrHAsEO +76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnK +OOK5Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvH +ugDnuL8BV8F3RTIMO/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7Hgvi +yJA/qIYM/PmLXoXLT1tLYhFHxUV8BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fL +buXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2G8kS1sHNzYDzAgE8yGnLRUhj +2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP +Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr +ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL +MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 +yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr +VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ +nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG +XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj +vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt +Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g +N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC +nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEc +MBoGA1UEChMTSmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRp +b25DQTAeFw0wNzEyMTIxNTAwMDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYT +AkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zlcm5tZW50MRYwFAYDVQQLEw1BcHBs +aWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp23gdE6H +j6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4fl+K +f5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55 +IrmTwcrNwVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cw +FO5cjFW6WY2H/CPek9AEjP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDiht +QWEjdnjDuGWk81quzMKq2edY3rZ+nYVunyoKb58DKTCXKB28t89UKU5RMfkntigm +/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRUWssmP3HMlEYNllPqa0jQ +k/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNVBAYTAkpQ +MRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOC +seODvOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADlqRHZ3ODrso2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJ +hyzjVOGjprIIC8CFqMjSnHH2HZ9g/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+ +eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYDio+nEhEMy/0/ecGc/WLuo89U +DNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmWdupwX3kSa+Sj +B1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL +rosot4LKGAfmt1t06SAZf7IbiVQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs +IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg +R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A +PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8 +Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL +TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL +5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7 +S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe +2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap +EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td +EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv +/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN +A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0 +abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF +I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz +4iIprn2DQKi6bA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIE9zCCA9+gAwIBAgIEPL/xoTANBgkqhkiG9w0BAQUFADB2MQswCQYDVQQGEwJQ +TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu +dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MSAwHgYDVQQDExdDQyBTaWduZXQgLSBQ +Q0EgS2xhc2EgMjAeFw0wMjA0MTkxMDI5NTNaFw0xNzA0MTgxMjUzMDdaMHUxCzAJ +BgNVBAYTAlBMMR8wHQYDVQQKExZUUCBJbnRlcm5ldCBTcC4geiBvLm8uMSQwIgYD +VQQLExtDZW50cnVtIENlcnR5ZmlrYWNqaSBTaWduZXQxHzAdBgNVBAMTFkNDIFNp +Z25ldCAtIENBIEtsYXNhIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCqgLJuQqY4yavbSgHg8CyfKTx4BokNSDOVz4eD9vptUr11Kqd06ED1hlH7Sg0g +oBFAfntNU/QTKwSBaNuime7C4sSEdgsKrPoAhGb4Mq8y7Ty7RqZz7mkzNMqzL2L2 +U4yQ2QjvpH8MH0IBqOWEcpSkpwnrCDImRoTfd+YlZWKi2JceQixUUYIQ45Ox8+x8 +hHbvvZdgqtcvo8PW27qoHkp/7hMuJ44kDAGrmxffBXl/OBRZp0uO1CSLcMcVJzyr +2phKhy406MYdWrtNPEluGs0GFDzd0nrIctiWAO4cmct4S72S9Q6e//0GO9f3/Ca5 +Kb2I1xYLj/xE+HgjHX9aD2MhAgMBAAGjggGMMIIBiDAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBBjCB4wYDVR0gBIHbMIHYMIHVBg0rBgEEAb4/AhQKAQEA +MIHDMHUGCCsGAQUFBwICMGkaZ0NlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmll +IHogZG9rdW1lbnRlbTogIlBvbGl0eWthIENlcnR5ZmlrYWNqaSBQQ0EyIC0gQ2Vy +dHlmaWthdHkgVXJ6ZWRvdyBLbGFzeSAyIi4wSgYIKwYBBQUHAgEWPmh0dHA6Ly93 +d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9kb2t1bWVudHkva2xhc2EyL3BjX3Bj +YTIudHh0MD8GA1UdHwQ4MDYwNKAyoDCGLmh0dHA6Ly93d3cuc2lnbmV0LnBsL3Jl +cG96eXRvcml1bS9jcmwvcGNhMi5jcmwwHwYDVR0jBBgwFoAUwGxGyl2CfpYHRonE +82AVXO08kMIwHQYDVR0OBBYEFLtFBlILy4HNKVSzvHxBTM0HDowlMA0GCSqGSIb3 +DQEBBQUAA4IBAQBWTsCbqXrXhBBev5v5cIuc6gJM8ww7oR0uMQRZoFSqvQUPWBYM +2/TLI/f8UM9hSShUVj3zEsSj/vFHagUVmzuVXo5u0WK8iaqATSyEVBhADHrPG6wY +cLKJlagge/ILA0m+SieyP2sjYD9MUB9KZIEyBKv0429UuDTw6P7pslxMWJBSNyQx +aLIs0SRKsqZZWkc7ZYAj2apSkBMX2Is1oHA+PwkF6jQMwCao/+CndXPUzfCF6caa +9WwW31W26MlXCvSmJgfiTPwGvm4PkPmOnmWZ3CczzhHl4q7ztHFzshJH3sZWDnrW +wBFjzz5ePr3WHV1wA7EY6oT4zBx+2gT9XBTB +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC+TCCAmKgAwIBAgIENvEbGTANBgkqhkiG9w0BAQUFADA2MQswCQYDVQQGEwJF +UzENMAsGA1UEChMERk5NVDEYMBYGA1UECxMPRk5NVCBDbGFzZSAyIENBMB4XDTk5 +MDMxODE0NTYxOVoXDTE5MDMxODE1MjYxOVowNjELMAkGA1UEBhMCRVMxDTALBgNV +BAoTBEZOTVQxGDAWBgNVBAsTD0ZOTVQgQ2xhc2UgMiBDQTCBnTANBgkqhkiG9w0B +AQEFAAOBiwAwgYcCgYEAmD+tGTaTPT7+dkIU/TVv8fqtInpY40bQXcZa+WItjzFe +/rQw/lB0rNadHeBixkndFBJ9cQusBsE/1waH4JCJ1uXjA7LyJ7GfM8iqazZKo8Q/ +eUGdiUYvKz5j1DhWkaodsQ1CdU3zh07jD03MtGy/YhOH6tCbjrbi/xn0lAnVlmEC +AQOjggEUMIIBEDARBglghkgBhvhCAQEEBAMCAAcwWAYDVR0fBFEwTzBNoEugSaRH +MEUxCzAJBgNVBAYTAkVTMQ0wCwYDVQQKEwRGTk1UMRgwFgYDVQQLEw9GTk1UIENs +YXNlIDIgQ0ExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5OTAzMTgxNDU2 +MTlagQ8yMDE5MDMxODE0NTYxOVowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFECa +dkSXdAfErBTLHo1POkV8MNdhMB0GA1UdDgQWBBRAmnZEl3QHxKwUyx6NTzpFfDDX +YTAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG +SIb3DQEBBQUAA4GBAGFMoHxZY1tm+O5lE85DgEe5sjXJyITHa3NgReSdN531jiW5 ++aqqyuP4Q5wvoIkFsUUylCoeA41dpt7PV5Xa3yZgX8vflR64zgjY+IrJT6lodZPj +LwVMZGACokIeb4ZoZVUO2ENv8pExPqNHPCgFr0W2nSJMJntLfVsV+RlG3whd +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX +DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 +qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp +uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU +Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE +pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp +5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M +UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN +GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy +5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv +6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK +eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 +B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ +BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov +L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG +SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS +CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen +5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 +IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK +gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL ++63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL +vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm +bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk +N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC +Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z +ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDcDCCAligAwIBAgIBBTANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMjAeFw0wNDEyMTMxNTAwMTBaFw0y +OTEyMDUxNTAwMTBaMFsxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRYwFAYDVQQDEw1Eb0Qg +Um9vdCBDQSAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwCzB9o07 +rP8/PNZxvrh0IgfscEEV/KtA4weqwcPYn/7aTDq/P8jYKHtLNgHArEUlw9IOCo+F +GGQQPRoTcCpvjtfcjZOzQQ84Ic2tq8I9KgXTVxE3Dc2MUfmT48xGSSGOFLTNyxQ+ +OM1yMe6rEvJl6jQuVl3/7mN1y226kTT8nvP0LRy+UMRC31mI/2qz+qhsPctWcXEF +lrufgOWARVlnQbDrw61gpIB1BhecDvRD4JkOG/t/9bPMsoGCsf0ywbi+QaRktWA6 +WlEwjM7eQSwZR1xJEGS5dKmHQa99brrBuKG/ZTE6BGf5tbuOkooAY7ix5ow4X4P/ +UNU7ol1rshDMYwIDAQABoz8wPTAdBgNVHQ4EFgQUSXS7DF66ev4CVO97oMaVxgmA +cJYwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBAJiRjT+JyLv1wGlzKTs1rLqzCHY9cAmS6YREIQF9FHYb7lFsHY0VNy17MWn0 +mkS4r0bMNPojywMnGdKDIXUr5+AbmSbchECV6KjSzPZYXGbvP0qXEIIdugqi3VsG +K52nZE7rLgE1pLQ/E61V5NVzqGmbEfGY8jEeb0DU+HifjpGgb3AEkGaqBivO4XqS +tX3h4NGW56E6LcyxnR8FRO2HmdNNGnA5wQQM5X7Z8a/XIA7xInolpHOZzD+kByeW +qKKV7YK5FtOeC4fCwfKI9WLfaN/HvGlR7bFc3FRUKQ8JOZqsA8HbDE2ubwp6Fknx +v5HSOJTT9pUst2zJQraNypCNhdk= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgIBBDANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJLUjEN +MAsGA1UECgwES0lTQTEuMCwGA1UECwwlS29yZWEgQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkgQ2VudHJhbDEWMBQGA1UEAwwNS0lTQSBSb290Q0EgMTAeFw0wNTA4MjQw +ODA1NDZaFw0yNTA4MjQwODA1NDZaMGQxCzAJBgNVBAYTAktSMQ0wCwYDVQQKDARL +SVNBMS4wLAYDVQQLDCVLb3JlYSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDZW50 +cmFsMRYwFAYDVQQDDA1LSVNBIFJvb3RDQSAxMIIBIDANBgkqhkiG9w0BAQEFAAOC +AQ0AMIIBCAKCAQEAvATk+hM58DSWIGtsaLv623f/J/es7C/n/fB/bW+MKs0lCVsk +9KFo/CjsySXirO3eyDOE9bClCTqnsUdIxcxPjHmc+QZXfd3uOPbPFLKc6tPAXXdi +8EcNuRpAU1xkcK8IWsD3z3X5bI1kKB4g/rcbGdNaZoNy4rCbvdMlFQ0yb2Q3lIVG +yHK+d9VuHygvx2nt54OJM1jT3qC/QOhDUO7cTWu8peqmyGGO9cNkrwYV3CmLP3WM +vHFE2/yttRcdbYmDz8Yzvb9Fov4Kn6MRXw+5H5wawkbMnChmn3AmPC7fqoD+jMUE +CSVPzZNHPDfqAmeS/vwiJFys0izgXAEzisEZ2wIBA6MyMDAwHQYDVR0OBBYEFL+2 +J9gDWnZlTGEBQVYx5Yt7OtnMMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEF +BQADggEBABOvUQveimpb5poKyLGQSk6hAp3MiNKrZr097LuxQpVqslxa/6FjZJap +aBV/JV6K+KRzwYCKhQoOUugy50X4TmWAkZl0Q+VFnUkq8JSV3enhMNITbslOsXfl +BM+tWh6UCVrXPAgcrnrpFDLBRa3SJkhyrKhB2vAhhzle3/xk/2F0KpzZm4tfwjeT +2KM3LzuTa7IbB6d/CVDv0zq+IWuKkDsnSlFOa56ch534eJAx7REnxqhZvvwYC/uO +fi5C4e3nCSG9uRPFVmf0JqZCQ5BEVLRxm3bkGhKsGigA35vB1fjbXKP4krG9tNT5 +UNkAAk/bg9ART6RCVmE6fhMy04Qfybo= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs +ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy +ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy +dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p +OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 +8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K +Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe +hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk +6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q +AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI +bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB +ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z +qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn +0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN +sSi6 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB +ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly +aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w +NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G +A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX +SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR +VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 +w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF +mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg +4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 +4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw +EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx +SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 +ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 +vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi +Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ +/L7fCg0= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEzzCCA7egAwIBAgIEO6ocGTANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQ +TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu +dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBS +b290Q0EwHhcNMDEwOTIwMTY0MjE5WhcNMjYwOTIxMTU0MjE5WjBxMQswCQYDVQQG +EwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMb +Q2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQg +LSBSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrr2vydnNp +ELfGW3KsARiDhJvwDtUe4AbWev+OfMc3+vA29nX8ZmIwno3gmItjo5DbUCCRiCMq +5c9epcGu+kg4a3BJChVXREl8gVh0ST15rr3RKrSc4VgsvQzl0ZUraeQLl8JoRT5P +LsUj3qwF78jUCQVckiiLVcnGfZtFCm+DCJXliQBDMB9XFAUEiO/DtEBs0B7wJGx7 +lgJeJpQUcGiaOPjcJDYOk7rNAYmmD2gWeSlepufO8luUYG/YDxTC4mqhRqfa4MnV +O5dqy+ICj2UvUpHbZDB0KfGRibgBYeQP1kuqgIzJN4UqknVAJb0aMBSPl+9k2fAU +dchx1njlbdcbAgMBAAGjggFtMIIBaTAPBgNVHRMBAf8EBTADAQH/MIIBBAYDVR0g +BIH8MIH5MIH2Bg0rBgEEAb4/AgEKAQEAMIHkMIGaBggrBgEFBQcCAjCBjRqBikNl +cnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmllIHogZG9rdW1lbnRlbTogIlBvbGl0 +eWthIENlcnR5ZmlrYWNqaSBkbGEgUm9vdENBIi4gQ2VydHlmaWthdCB3eXN0YXdp +b255IHByemV6IFJvb3RDQSB3IGhpZXJhcmNoaWkgQ0MgU2lnbmV0LjBFBggrBgEF +BQcCARY5aHR0cDovL3d3dy5zaWduZXQucGwvcmVwb3p5dG9yaXVtL2Rva3VtZW50 +eS9wY19yb290Y2EudHh0MB0GA1UdDgQWBBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAf +BgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAOBgNVHQ8BAf8EBAMCAQYw +DQYJKoZIhvcNAQEFBQADggEBAGnY5QmYqnnO9OqFOWZxxb25UHRnaRF6IV9aaGit +5BZufZj2Tq3v8L3SgE34GOoIcdRMMG5JEpEU4mN/Ef3oY6Eo+7HfqaPHI4KFmbDS +PiK5s+wmf+bQSm0Yq5/h4ZOdcAESlLQeLSt1CQk2JoKQJ6pyAf6xJBgWEIlm4RXE +4J3324PUiOp83kW6MDvaa1xY976WyInr4rwoLgxVl11LZeKWha0RJJxJgw/NyWpK +G7LWCm1fglF8JH51vZNndGYq1iKtfnrIOvLZq6bzaCiZm1EurD8HE6P7pmABKK6o +3C2OXlNfNIgwkDN/cDqk5TYsTkrpfriJPdxXBH8hQOkW89g= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM +HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK +qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj +cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y +cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP +T8qAkbYp +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i +2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ +2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIH/zCCB2igAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm +SVBTIENBIENMQVNFQTEgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT +JklQUyBDQSBDTEFTRUExIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI +hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjMxMTEyMTQxWhcNMjUxMjI5 +MTEyMTQxWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM8g89BgSKoCxBXZ5C+NnlURLSnM +UWZoAGXaFFWf6q7f69uN1nXaUfTEzPstvTUfE7fpZmF8lEDz+2AvjBg086hVnra0 +b0APA0VnanJyW2ZIlkKFGMCB4WJqh7JB7i45jITVXthPV2vsjlKM97Pnnhimz8Fb +r+RZcsz69vRptMqxAgMBAAGjggRbMIIEVzAdBgNVHQ4EFgQUL8zsbGe+T/iqPIiN +EvvHnUxb9F4wggFGBgNVHSMEggE9MIIBOYAUL8zsbGe+T/iqPIiNEvvHnUxb9F6h +ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC +AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF +BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB +BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg +hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud +EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBDBglghkgBhvhCAQ0ENhY0Q0xBU0VBMSBD +QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cHM6Ly93d3cuaXBzLmVzLzAqBglg +hkgBhvhCAQIEHRYbaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDwGCWCGSAGG ++EIBBAQvFi1odHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VB +MS5jcmwwQQYJYIZIAYb4QgEDBDQWMmh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMyMDAy +L3Jldm9jYXRpb25DTEFTRUExLmh0bWw/MD4GCWCGSAGG+EIBBwQxFi9odHRwczov +L3d3dy5pcHMuZXMvaXBzMjAwMi9yZW5ld2FsQ0xBU0VBMS5odG1sPzA8BglghkgB +hvhCAQgELxYtaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VB +MS5odG1sMHcGA1UdHwRwMG4wM6AxoC+GLWh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMy +MDAyL2lwczIwMDJDTEFTRUExLmNybDA3oDWgM4YxaHR0cHM6Ly93d3diYWNrLmlw +cy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRUExLmNybDAvBggrBgEFBQcBAQQjMCEw +HwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQAD +gYEAGY2khC4v4mlenqRcy8Mn8mcWca88t4CY9LCJMqlIt7i559BNkMMB66tXsNp9 +N2QhnTordKOjkdgZJmCb7DUdMJEQQT0Y5W7JA6WvHatAFu8feRJ4ImaTjI0Xz3Dd +Jbz6O++igCw0l4EY5gayn2BFpAm+7ZpEcdpR/OCOH80lNDo= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJE +SzEVMBMGA1UEChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQg +Um9vdCBDQTAeFw0wMTA0MDUxNjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNV +BAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJuZXQxHTAbBgNVBAsTFFREQyBJbnRl +cm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLhA +vJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20jxsNu +Zp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a +0vnRrEvLznWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc1 +4izbSysseLlJ28TQx5yc5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGN +eGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcD +R0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZIAYb4QgEBBAQDAgAHMGUG +A1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMMVERDIElu +dGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxME +Q1JMMTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3 +WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAw +HQYDVR0OBBYEFGxkAcf9hW2syNqeUAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJ +KoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQBO +Q8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540mgwV5dOy0uaOX +wTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ +2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm89 +9qNLPg7kbWzbO0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0 +jUNAE4z9mQNUecYu6oah9jrUCbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38 +aQNiuJkFBT1reBK9sG9l +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 +GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ ++mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd +U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm +NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY +ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ +ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 +CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq +g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm +fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c +2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ +bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 +MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK +EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh +BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq +xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G +87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i +2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U +WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 +0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G +A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr +pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL +ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm +aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv +hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm +hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X +dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 +P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y +iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no +xqE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT +ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw +MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj +dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l +c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC +UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc +58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ +o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr +aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA +A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA +Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv +8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp +IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi +BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw +MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig +YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v +dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ +BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 +papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K +DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 +KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox +XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFUjCCBDqgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJLUjEN +MAsGA1UEChMES0lTQTEuMCwGA1UECxMlS29yZWEgQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkgQ2VudHJhbDEWMBQGA1UEAxMNS0lTQSBSb290Q0EgMzAeFw0wNDExMTkw +NjM5NTFaFw0xNDExMTkwNjM5NTFaMGQxCzAJBgNVBAYTAktSMQ0wCwYDVQQKEwRL +SVNBMS4wLAYDVQQLEyVLb3JlYSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDZW50 +cmFsMRYwFAYDVQQDEw1LSVNBIFJvb3RDQSAzMIIBIDANBgkqhkiG9w0BAQEFAAOC +AQ0AMIIBCAKCAQEA3rrtF2Wu0b1KPazbgHLMWOHn4ZPazDB6z+8Lri2nQ6u/p0LP +CFYIpEcdffqG79gwlyY0YTyADvjU65/8IjAboW0+40zSVU4WQDfC9gdu2we1pYyW +geKbXH6UYcjOhDyx+gDmctMJhXfp3F4hT7TkTvTiF6tQrxz/oTlYdVsSspa5jfBw +YkhbVigqpYeRNrkeJPW5unu2UlFbF1pgBWycwubGjD756t08jP+J3kNwrB248XXN +OMpTDUdoasY8GMq94bS+DvTQ49IT+rBRERHUQavo9DmO4TSETwuTqmo4/OXGeEeu +dhf6oYA3BgAVCP1rI476cg2V1ktisWjC3TSbXQIBA6OCAg8wggILMB8GA1UdIwQY +MBaAFI+B8NqmzXQ8vmb0FWtGpP4GKMyqMB0GA1UdDgQWBBSPgfDaps10PL5m9BVr +RqT+BijMqjAOBgNVHQ8BAf8EBAMCAQYwggEuBgNVHSAEggElMIIBITCCAR0GBFUd +IAAwggETMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LnJvb3RjYS5vci5rci9yY2Ev +Y3BzLmh0bWwwgd4GCCsGAQUFBwICMIHRHoHOx3QAIMd4yZ3BHLKUACCs9cd4x3jJ +ncEcx4WyyLLkACgAVABoAGkAcwAgAGMAZQByAHQAaQBmAGkAYwBhAHQAZQAgAGkA +cwAgAGEAYwBjAHIAZQBkAGkAdABlAGQAIAB1AG4AZABlAHIAIABFAGwAZQBjAHQA +cgBvAG4AaQBjACAAUwBpAGcAbgBhAHQAdQByAGUAIABBAGMAdAAgAG8AZgAgAHQA +aABlACAAUgBlAHAAdQBiAGwAaQBjACAAbwBmACAASwBvAHIAZQBhACkwMwYDVR0R +BCwwKqQoMCYxJDAiBgNVBAMMG+2VnOq1reygleuztOuztO2YuOynhO2dpeybkDAz +BgNVHRIELDAqpCgwJjEkMCIGA1UEAwwb7ZWc6rWt7KCV67O067O07Zi47KeE7Z2l +7JuQMA8GA1UdEwEB/wQFMAMBAf8wDAYDVR0kBAUwA4ABADANBgkqhkiG9w0BAQUF +AAOCAQEAz9b3Dv2wjG4FFY6oXCuyWtEeV6ZeGKqCEQj8mbdbp+PI0qLT+SQ09+Pk +rolUR9NpScmAwRHr4inH9gaLX7riXs+rw87P7pIl3J85Hg4D9N6QW6FwmVzHc07J +pHVJeyWhn4KSjU3sYcUMMqfHODiAVToqgx2cZHm5Dac1Smjvj/8F2LpOVmHY+Epw +mAiWk9hgxzrsX58dKzVPSBShmrtv7tIDhlPxEMcHVGJeNo7iHCsdF03m9VrvirqC +6HfZKBF+N4dKlArJQOk1pTr7ZD7yXxZ683bXzu4/RB1Fql8RqlMcOh9SUWJUD6OQ +Nc9Nb7rHviwJ8TX4Absk3TC8SA/u2Q== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgIQKTZHquOKrIZKI1byyrdhrzANBgkqhkiG9w0BAQUFADBO +MQswCQYDVQQGEwJ1czEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQ0wCwYDVQQL +EwRGQkNBMRYwFAYDVQQDEw1Db21tb24gUG9saWN5MB4XDTA3MTAxNTE1NTgwMFoX +DTI3MTAxNTE2MDgwMFowTjELMAkGA1UEBhMCdXMxGDAWBgNVBAoTD1UuUy4gR292 +ZXJubWVudDENMAsGA1UECxMERkJDQTEWMBQGA1UEAxMNQ29tbW9uIFBvbGljeTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJeNvTMn5K1b+3i9L0dHbsd4 +6ZOcpN7JHP0vGzk4rEcXwH53KQA7Ax9oD81Npe53uCxiazH2+nIJfTApBnznfKM9 +hBiKHa4skqgf6F5PjY7rPxr4nApnnbBnTfAu0DDew5SwoM8uCjR/VAnTNr2kSVdS +c+md/uRIeUYbW40y5KVIZPMiDZKdCBW/YDyD90ciJSKtKXG3d+8XyaK2lF7IMJCk +FEhcVlcLQUwF1CpMP64Sm1kRdXAHImktLNMxzJJ+zM2kfpRHqpwJCPZLr1LoakCR +xVW9QLHIbVeGlRfmH3O+Ry4+i0wXubklHKVSFzYIWcBCvgortFZRPBtVyYyQd+sC +AwEAAaN7MHkwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFC9Yl9ipBZilVh/72at17wI8NjTHMBIGCSsGAQQBgjcVAQQFAgMBAAEwIwYJ +KwYBBAGCNxUCBBYEFHa3YJbdFFYprHWF03BjwbxHhhyLMA0GCSqGSIb3DQEBBQUA +A4IBAQBgrvNIFkBypgiIybxHLCRLXaCRc+1leJDwZ5B6pb8KrbYq+Zln34PFdx80 +CTj5fp5B4Ehg/uKqXYeI6oj9XEWyyWrafaStsU+/HA2fHprA1RRzOCuKeEBuMPdi +4c2Z/FFpZ2wR3bgQo2jeJqVW/TZsN5hs++58PGxrcD/3SDcJjwtCga1GRrgLgwb0 +Gzigf0/NC++DiYeXHIowZ9z9VKEDfgHLhUyxCynDvux84T8PCVI8L6eaSP436REG +WOE2QYrEtr+O3c5Ks7wawM36GpnScZv6z7zyxFSjiDV2zBssRm8MtNHDYXaSdBHq +S4CNHIkRi+xb/xfJSPzn4AYR4oRe +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOc +UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx +c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xS +S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg +SGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4XDTA3MTIyNTE4Mzcx +OVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxla3Ry +b25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMC +VFIxDzANBgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDE +sGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7F +ni4gKGMpIEFyYWzEsWsgMjAwNzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9NYvDdE3ePYakqtdTyuTFY +KTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQvKUmi8wUG ++7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveG +HtyaKhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6P +IzdezKKqdfcYbwnTrqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M +733WB2+Y8a+xwXrXgTW4qhe04MsCAwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHk +Yb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/sPx+EnWVUXKgW +AkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I +aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5 +mxRZNTZPz/OOXl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsa +XRik7r4EW5nVcV9VZWRi1aKbBFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZ +qxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAKpoRq0Tl9 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIIQTCCB6qgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCAR4xCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjE0MDIGA1UECxMr +SVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE0MDIG +A1UEAxMrSVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eTEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIzMTExMjY0 +M1oXDTI1MTIyOTExMjY0M1owggEeMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFy +Y2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5l +dCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlw +cy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxNDAyBgNVBAsTK0lQUyBDQSBUaW1lc3Rh +bXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxNDAyBgNVBAMTK0lQUyBDQSBU +aW1lc3RhbXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHjAcBgkqhkiG9w0B +CQEWD2lwc0BtYWlsLmlwcy5lczCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA +0umTdn+FPP2gAb0RL0ZCDyt/BZvGa/VRcayaUh8flSfMkO+WP45RNv0WAM43pSGU +Rmvt5P+hfuqf0aKbOPMTxLmYumVFQ/nXvRWdlC4AYN6YGrk8yfXh/NbEJN/n48iE +GRK0HFyz9eIWYSdg8vAt5PDzrPigeYSdReL2AfBE5ZECAwEAAaOCBIkwggSFMB0G +A1UdDgQWBBSR2UK8nKnK0Bw3E1JXFqANHikdPjCCAVAGA1UdIwSCAUcwggFDgBSR +2UK8nKnK0Bw3E1JXFqANHikdPqGCASakggEiMIIBHjELMAkGA1UEBhMCRVMxEjAQ +BgNVBAgTCUJhcmNlbG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJ +UFMgSW50ZXJuZXQgcHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJp +cHNAbWFpbC5pcHMuZXMgQy5JLkYuICBCLTYwOTI5NDUyMTQwMgYDVQQLEytJUFMg +Q0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTQwMgYDVQQD +EytJUFMgQ0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4w +HAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAM +BgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYB +BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIB +FgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYD +VR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlw +cy5lczBIBglghkgBhvhCAQ0EOxY5VGltZXN0YW1waW5nIENBIENlcnRpZmljYXRl +IGlzc3VlZCBieSBodHRwczovL3d3dy5pcHMuZXMvMCoGCWCGSAGG+EIBAgQdFhto +dHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi8wQQYJYIZIAYb4QgEEBDQWMmh0dHBz +Oi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMEYG +CWCGSAGG+EIBAwQ5FjdodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9yZXZvY2F0 +aW9uVGltZXN0YW1waW5nLmh0bWw/MEMGCWCGSAGG+EIBBwQ2FjRodHRwczovL3d3 +dy5pcHMuZXMvaXBzMjAwMi9yZW5ld2FsVGltZXN0YW1waW5nLmh0bWw/MEEGCWCG +SAGG+EIBCAQ0FjJodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lUaW1l +c3RhbXBpbmcuaHRtbDCBgQYDVR0fBHoweDA4oDagNIYyaHR0cHM6Ly93d3cuaXBz +LmVzL2lwczIwMDIvaXBzMjAwMlRpbWVzdGFtcGluZy5jcmwwPKA6oDiGNmh0dHBz +Oi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyVGltZXN0YW1waW5nLmNy +bDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5l +cy8wDQYJKoZIhvcNAQEFBQADgYEAxKMCdGABCUwYXU900W1zDCfTSDC1TxFVGRnH +I4soqfp4D34sJ/adkgD2GMgkAMVf+C1MY/yQFV4nmOal9K7SNrG1JR8OeDoRjpM4 +rtO9qYbuHD3TW47/y/aZSZxP4ccocGpPOkvqfrnndKRKY0WUk/7Qg5aqpIXni2Gg +olkTZbQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC +Q04xMjAwBgNVBAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24g +Q2VudGVyMUcwRQYDVQQDDD5DaGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0 +aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMgUm9vdDAeFw0xMDA4MzEwNzExMjVa +Fw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEg +SW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNo +aW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRp +ZmljYXRlcyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z +7r07eKpkQ0H1UN+U8i6yjUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA// +DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV98YPjUesWgbdYavi7NifFy2cyjw1l1Vx +zUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2HklY0bBoQCxfVWhyXWIQ8 +hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23KzhmBsUs +4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54u +gQEC7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oY +NJKiyoOCWTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E +FgQUfHJLOcfA22KlT5uqGDSSosqDglkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3 +j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd50XPFtQO3WKwMVC/GVhMPMdoG +52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM7+czV0I664zB +echNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws +ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrI +zo9uoV1/A3U05K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATy +wy39FCqQmbkHzJ8= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP +bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2 +MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft +ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk +hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym +1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW +OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb +2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko +O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU +AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF +Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb +LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir +oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C +MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds +sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy +NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD +cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs +2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY +JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE +Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ +n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A +PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCB +ozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3Qt +TmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5WhcNMTkwNzA5MTg1 +NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0 +IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYD +VQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VS +Rmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQCz+5Gh5DZVhawGNFugmliy+LUPBXeDrjKxdpJo7CNKyXY/45y2 +N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4CjDUeJT1FxL+78P/m4FoCH +iZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXuOzr0hARe +YFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1 +axwiP8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6g +yN7igEL66S/ozjIEj3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQD +AgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPh +ahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9V +VE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0GCSqGSIb3DQEB +BQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y +IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6Lzs +QCv4AdRWOOTKRIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4 +ZSfP1FMa8Kxun08FDAOBp4QpxFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qM +YEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAqDbUMo2s/rn9X9R+WfN9v3YIwLGUb +QErNaLly7HF27FSOH4UMAWr6pjisH8SE +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy +c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD +VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 +c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 +WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG +FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq +XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL +se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb +KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd +IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 +y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt +hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc +QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 +Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV +HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ +KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ +L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr +Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo +ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY +T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz +GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m +1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV +OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH +6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX +QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE +BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWdu +IFBsYXRpbnVtIENBIC0gRzIwHhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAw +WjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMSMwIQYDVQQD +ExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu669y +IIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2Htn +IuJpX+UFeNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+ +6ixuEFGSzH7VozPY1kneWCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5ob +jM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIoj5+saCB9bzuohTEJfwvH6GXp43gOCWcw +izSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/68++QHkwFix7qepF6w9fl ++zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34TaNhxKFrY +zt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaP +pZjydomyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtF +KwH3HBqi7Ri6Cr2D+m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuW +ae5ogObnmLo2t/5u7Su9IPhlGdpVCX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMB +AAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCvzAeHFUdvOMW0 +ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW +IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUA +A4ICAQAIhab1Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0 +uMoI3LQwnkAHFmtllXcBrqS3NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+ +FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4U99REJNi54Av4tHgvI42Rncz7Lj7 +jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8KV2LwUvJ4ooTHbG/ +u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl9x8D +YSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1 +puEa+S1BaYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXa +icYwu+uPyyIIoK6q8QNsOktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbG +DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x +kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z +Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW @@ -2862,100 +4449,73 @@ um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIFFjCCBH+gAwIBAgIBADANBgkqhkiG9w0BAQQFADCBsDELMAkGA1UEBhMCSUwx -DzANBgNVBAgTBklzcmFlbDEOMAwGA1UEBxMFRWlsYXQxFjAUBgNVBAoTDVN0YXJ0 -Q29tIEx0ZC4xGjAYBgNVBAsTEUNBIEF1dGhvcml0eSBEZXAuMSkwJwYDVQQDEyBG -cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYS -YWRtaW5Ac3RhcnRjb20ub3JnMB4XDTA1MDMxNzE3Mzc0OFoXDTM1MDMxMDE3Mzc0 -OFowgbAxCzAJBgNVBAYTAklMMQ8wDQYDVQQIEwZJc3JhZWwxDjAMBgNVBAcTBUVp -bGF0MRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMRowGAYDVQQLExFDQSBBdXRob3Jp -dHkgRGVwLjEpMCcGA1UEAxMgRnJlZSBTU0wgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkxITAfBgkqhkiG9w0BCQEWEmFkbWluQHN0YXJ0Y29tLm9yZzCBnzANBgkqhkiG -9w0BAQEFAAOBjQAwgYkCgYEA7YRgACOeyEpRKSfeOqE5tWmrCbIvNP1h3D3TsM+x -18LEwrHkllbEvqoUDufMOlDIOmKdw6OsWXuO7lUaHEe+o5c5s7XvIywI6Nivcy+5 -yYPo7QAPyHWlLzRMGOh2iCNJitu27Wjaw7ViKUylS7eYtAkUEKD4/mJ2IhULpNYI -LzUCAwEAAaOCAjwwggI4MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgHmMB0G -A1UdDgQWBBQcicOWzL3+MtUNjIExtpidjShkjTCB3QYDVR0jBIHVMIHSgBQcicOW -zL3+MtUNjIExtpidjShkjaGBtqSBszCBsDELMAkGA1UEBhMCSUwxDzANBgNVBAgT -BklzcmFlbDEOMAwGA1UEBxMFRWlsYXQxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4x -GjAYBgNVBAsTEUNBIEF1dGhvcml0eSBEZXAuMSkwJwYDVQQDEyBGcmVlIFNTTCBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYSYWRtaW5Ac3Rh -cnRjb20ub3JnggEAMB0GA1UdEQQWMBSBEmFkbWluQHN0YXJ0Y29tLm9yZzAdBgNV -HRIEFjAUgRJhZG1pbkBzdGFydGNvbS5vcmcwEQYJYIZIAYb4QgEBBAQDAgAHMC8G -CWCGSAGG+EIBDQQiFiBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAy -BglghkgBhvhCAQQEJRYjaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL2NhLWNybC5j -cmwwKAYJYIZIAYb4QgECBBsWGWh0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy8wOQYJ -YIZIAYb4QgEIBCwWKmh0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9pbmRleC5waHA/ -YXBwPTExMTANBgkqhkiG9w0BAQQFAAOBgQBscSXhnjSRIe/bbL0BCFaPiNhBOlP1 -ct8nV0t2hPdopP7rPwl+KLhX6h/BquL/lp9JmeaylXOWxkjHXo0Hclb4g4+fd68p -00UOpO6wNnQt8M2YI3s3S9r+UZjEHjQ8iP2ZO1CnwYszx8JSFhKVU2Ui77qLzmLb -cCOxgN8aIDjnfg== +MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm +SVBTIENBIENMQVNFQTEgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT +JklQUyBDQSBDTEFTRUExIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI +hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjI5MDEwNTMyWhcNMjUxMjI3 +MDEwNTMyWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALsw19zQVL01Tp/FTILq0VA8R5j8 +m2mdd81u4D/u6zJfX5/S0HnllXNEITLgCtud186Nq1KLK3jgm1t99P1tCeWu4Wwd +ByOgF9H5fahGRpEiqLJpxq339fWUoTCUvQDMRH/uxJ7JweaPCjbB/SQ9AaD1e+J8 +eGZDi09Z8pvZ+kmzAgMBAAGjggRTMIIETzAdBgNVHQ4EFgQUZyaW56G/2LUDnf47 +3P7yiuYV3TAwggFGBgNVHSMEggE9MIIBOYAUZyaW56G/2LUDnf473P7yiuYV3TCh +ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC +AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF +BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB +BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg +hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud +EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0VBMSBD +QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cDovL3d3dy5pcHMuZXMvMCkGCWCG +SAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyLzA7BglghkgBhvhC +AQQELhYsaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VBMS5j +cmwwQAYJYIZIAYb4QgEDBDMWMWh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2 +b2NhdGlvbkNMQVNFQTEuaHRtbD8wPQYJYIZIAYb4QgEHBDAWLmh0dHA6Ly93d3cu +aXBzLmVzL2lwczIwMDIvcmVuZXdhbENMQVNFQTEuaHRtbD8wOwYJYIZIAYb4QgEI +BC4WLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VBMS5odG1s +MHUGA1UdHwRuMGwwMqAwoC6GLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvaXBz +MjAwMkNMQVNFQTEuY3JsMDagNKAyhjBodHRwOi8vd3d3YmFjay5pcHMuZXMvaXBz +MjAwMi9pcHMyMDAyQ0xBU0VBMS5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF +BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAH66iqyA +AIQVCtWYUQxkxZwCWINmyq0eB81+atqAB98DNEock8RLWCA1NnHtogo1EqWmZaeF +aQoO42Hu6r4okzPV7Oi+xNtff6j5YzHIa5biKcJboOeXNp13XjFr/tOn2yrb25aL +H2betgPAK7N41lUH5Y85UN4HI3LmvSAUS7SG -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV -BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln -biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF -MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT -d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 -76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ -bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c -6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE -emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd -MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt -MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y -MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y -FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi -aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM -gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB -qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 -lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn -8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov -L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 -45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO -UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 -O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC -bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv -GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a -77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC -hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 -92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp -Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w -ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt -Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE -BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWdu -IFBsYXRpbnVtIENBIC0gRzIwHhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAw -WjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMSMwIQYDVQQD -ExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu669y -IIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2Htn -IuJpX+UFeNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+ -6ixuEFGSzH7VozPY1kneWCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5ob -jM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIoj5+saCB9bzuohTEJfwvH6GXp43gOCWcw -izSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/68++QHkwFix7qepF6w9fl -+zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34TaNhxKFrY -zt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaP -pZjydomyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtF -KwH3HBqi7Ri6Cr2D+m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuW -ae5ogObnmLo2t/5u7Su9IPhlGdpVCX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMB -AAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O -BBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCvzAeHFUdvOMW0 -ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW -IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUA -A4ICAQAIhab1Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0 -uMoI3LQwnkAHFmtllXcBrqS3NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+ -FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4U99REJNi54Av4tHgvI42Rncz7Lj7 -jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8KV2LwUvJ4ooTHbG/ -u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl9x8D -YSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1 -puEa+S1BaYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXa -icYwu+uPyyIIoK6q8QNsOktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbG -DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x -kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z -Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g== +MIIEGjCCAwKgAwIBAgIDAYagMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYDVQQGEwJG +STEQMA4GA1UECBMHRmlubGFuZDEhMB8GA1UEChMYVmFlc3RvcmVraXN0ZXJpa2Vz +a3VzIENBMSkwJwYDVQQLEyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBTZXJ2aWNl +czEZMBcGA1UECxMQVmFybWVubmVwYWx2ZWx1dDEZMBcGA1UEAxMQVlJLIEdvdi4g +Um9vdCBDQTAeFw0wMjEyMTgxMzUzMDBaFw0yMzEyMTgxMzUxMDhaMIGjMQswCQYD +VQQGEwJGSTEQMA4GA1UECBMHRmlubGFuZDEhMB8GA1UEChMYVmFlc3RvcmVraXN0 +ZXJpa2Vza3VzIENBMSkwJwYDVQQLEyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBT +ZXJ2aWNlczEZMBcGA1UECxMQVmFybWVubmVwYWx2ZWx1dDEZMBcGA1UEAxMQVlJL +IEdvdi4gUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALCF +FdrIAzfQo0Y3bBseljDCWoUSZyPyu5/nioFgJ/gTqTy894aqqvTzJSm0/nWuHoGG +igWyHWWyOOi0zCia+xc28ZPVec7Bg4shT8MNrUHfeJ1I4x9CRPw8bSEga60ihCRC +jxdNwlAfZM0tOSJWiP2yY51U2kJpwMhP1xjiPshphJQ9LIDGfM6911Mf64i5psu7 +hVfvV3ZdDIvTXhJBnyHAOfQmbQj6OLOhd7HuFtjQaNq0mKWgZUZKa41+qk1guPjI +DfxxPu45h4G02fhukO4/DmHXHSto5i7hQkQmeCxY8n0Wf2HASSQqiYe2XS8pGfim +545SnkFLWg6quMJmQlMCAwEAAaNVMFMwDwYDVR0TAQH/BAUwAwEB/zARBglghkgB +hvhCAQEEBAMCAAcwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBTb6eGb0tEkC/yr +46Bn6q6cS3f0sDANBgkqhkiG9w0BAQUFAAOCAQEArX1ID1QRnljurw2bEi8hpM2b +uoRH5sklVSPj3xhYKizbXvfNVPVRJHtiZ+GxH0mvNNDrsczZog1Sf0JLiGCXzyVy +t08pLWKfT6HAVVdWDsRol5EfnGTCKTIB6dTI2riBmCguGMcs/OubUpbf9MiQGS0j +8/G7cdqehSO9Gu8u5Hp5t8OdhkktY7ktdM9lDzJmid87Ie4pbzlj2RXBbvbfgD5Q +eBmK3QOjFKU3p7UsfLYRh+cF8ry23tT/l4EohP7+bEaFEEGfTXWMB9SZZ291im/k +UJL2mdUQuMSpe/cXjUu/15WfCdxEDx4yw8DP03kN5Mc7h/CQNIghYkmSBAQfvA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE @@ -3025,53 +4585,24 @@ zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6 MBr1mmz0DlP5OlvRHA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOc -UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx -c8SxMQswCQYDVQQGDAJUUjEPMA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykg -MjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 -dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMxMDI3MTdaFw0xNTAz -MjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2Vy -dGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYD -VQQHDAZBTktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kg -xLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEu -xZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7 -XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GXyGl8hMW0kWxsE2qkVa2k -heiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8iSi9BB35J -YbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5C -urKZ8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1 -JuTm5Rh8i27fbMx4W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51 -b0dewQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV -9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46sWrv7/hg0Uw2ZkUd82YCdAR7 -kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxEq8Sn5RTOPEFh -fEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy -B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdA -aLX/7KfS0zgYnNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKS -RGQDJereW26fyfJOrN3H ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOc -UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx -c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xS -S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg -SGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcNMDUxMTA3MTAwNzU3 -WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVrdHJv -bmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJU -UjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSw -bGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWe -LiAoYykgS2FzxLFtIDIwMDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqeLCDe2JAOCtFp0if7qnef -J1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKIx+XlZEdh -R3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJ -Qv2gQrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGX -JHpsmxcPbe9TmJEr5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1p -zpwACPI2/z7woQ8arBT9pmAPAgMBAAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58S -Fq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8GA1UdEwEB/wQFMAMBAf8wDQYJ -KoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/nttRbj2hWyfIvwq -ECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 -Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFz -gw2lGh1uEpJ+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotH -uFEJjOp9zYhys2AzsfAKRO8P9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LS -y3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5UrbnBEI= +MIIDQzCCAiugAwIBAgIQX/h7KCtU3I1CoxW1aMmt/zANBgkqhkiG9w0BAQUFADA1 +MRYwFAYDVQQKEw1DaXNjbyBTeXN0ZW1zMRswGQYDVQQDExJDaXNjbyBSb290IENB +IDIwNDgwHhcNMDQwNTE0MjAxNzEyWhcNMjkwNTE0MjAyNTQyWjA1MRYwFAYDVQQK +Ew1DaXNjbyBTeXN0ZW1zMRswGQYDVQQDExJDaXNjbyBSb290IENBIDIwNDgwggEg +MA0GCSqGSIb3DQEBAQUAA4IBDQAwggEIAoIBAQCwmrmrp68Kd6ficba0ZmKUeIhH +xmJVhEAyv8CrLqUccda8bnuoqrpu0hWISEWdovyD0My5jOAmaHBKeN8hF570YQXJ +FcjPFto1YYmUQ6iEqDGYeJu5Tm8sUxJszR2tKyS7McQr/4NEb7Y9JHcJ6r8qqB9q +VvYgDxFUl4F1pyXOWWqCZe+36ufijXWLbvLdT6ZeYpzPEApk0E5tzivMW/VgpSdH +jWn0f84bcN5wGyDWbs2mAag8EtKpP6BrXruOIIt6keO1aO6g58QBdKhTCytKmg9l +Eg6CTY5j/e/rmxrbU6YTYK/CfdfHbBcl1HP7R2RQgYCUTOG/rksc35LtLgXfAgED +o1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUJ/PI +FR5umgIJFq0roIlgX9p7L6owEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEF +BQADggEBAJ2dhISjQal8dwy3U8pORFBi71R803UXHOjgxkhLtv5MOhmBVrBW7hmW +Yqpao2TB9k5UM8Z3/sUcuuVdJcr18JOagxEu5sv4dEX+5wW4q+ffy0vhN4TauYuX +cB7w4ovXsNgOnbFp1iqRe6lJT37mjpXYgyc81WhJDtSd9i7rp77rMKSsH0T8lasz +Bvt9YAretIpjsJyp8qS5UwGH0GikJ3+r/+n6yUA4iGe0OcaEb1fJU9u6ju7AQ7L4 +CYNu/2bPPu8Xs1gYJQk0XuPL1hS27PKSb3TkL4Eq1ZKR4OCXPDJoBYVL0fdX4lId +kxpUnwVwwEpxYB5DC2Ae/qPOgRnhCzU= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ @@ -3106,80 +4637,188 @@ LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl pYYsfPQS -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 -nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex -t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz -SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG -BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ -rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ -NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E -BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH -BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv -MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE -p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y -5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK -WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ -4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N -hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 +Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW +KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw +NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw +NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy +ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV +BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo +Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 +4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 +KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI +rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi +94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB +sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi +gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo +kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE +vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t +O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua +AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP +9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ +eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m +0vdXcDazv/wor3ElhVsT/h5/WrQ8 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9v -dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDAxMDExMTY0MTI4WhcNMjEwMTE0 -MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSww -KgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0G -A1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n13 -5zHCLielTWi5MbqNQ1mXx3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHE -SxP9cMIlrCL1dQu3U+SlK93OvRw6esP3E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4O -JgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5OEL8pahbSCOz6+MlsoCu -ltQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4jsNtlAHCE -AQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMB -AAGjYTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcB -CzAyMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRw -b2xpY3kwDQYJKoZIhvcNAQEFBQADggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo -7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrvm+0fazbuSCUlFLZWohDo7qd/ -0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0ROhPs7fpvcmR7 -nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx -x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ -33ZwmVxwQ023tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY +MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo +R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx +MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 +AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA +ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 +7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W +kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI +mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ +KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 +6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl +4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K +oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj +UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU +AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB -gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk -MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY -UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx -NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 -dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy -dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 -38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP -KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q -DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 -qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa -JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi -PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P -BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs -jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 -eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD -ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR -vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt -qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa -IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy -i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ -O+7ETPTsJ3xCwnR8gooJybQDJbw= +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz +MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw +IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR +dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp +li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D +rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ +WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug +F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU +xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC +Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv +dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw +ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl +IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh +c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy +ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI +KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T +KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq +y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p +dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD +VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL +MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk +fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 +7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R +cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y +mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW +xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK +SnQ2+Q== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMx +IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1 +dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w +HhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTELMAkGA1UEBhMCRVMx +IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1 +dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5u +Cp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5Vj1H5WuretXDE7aTt/6MNbg9kUDGvASdY +rv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJHlShbz++AbOCQl4oBPB3z +hxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf3H5idPay +BQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcL +iam8NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcb +AgMBAAGjgZ8wgZwwKgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lv +bmFsLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0 +MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E +FgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQADggEBAEdz/o0n +VPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq +u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36m +hoEyIwOdyPdfwUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzfl +ZKG+TQyTmAyX9odtsz/ny4Cm7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBp +QWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YGVM+h4k0460tQtcsm9MracEpqoeJ5 +quGnM/b9Sh/22WA= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 +aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla +MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD +VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW +fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt +TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL +fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW +1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 +kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G +A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v +ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo +dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu +Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ +HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 +pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS +jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ +xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn +dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 +nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO +8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV +ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb +PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 +6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr +n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a +qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 +wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 +ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs +pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 +E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL +MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV +BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 +Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1 +OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i +SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc +VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf +tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg +uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J +XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK +8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99 +5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3 +kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy +dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6 +Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz +JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 +Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS +GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt +ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8 +au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV +hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI +dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB @@ -3207,6 +4846,477 @@ LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 jVaMaA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx +MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o +Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt +5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s +3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej +vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu +8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil +zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ +3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD +FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 +Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 +ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx +MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB +ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV +BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV +6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX +GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP +dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH +1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF +62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW +BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL +MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU +cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv +b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 +IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ +iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao +GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh +4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm +XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIH6jCCB1OgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl +SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl +SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 +DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAxMDE0NFoXDTI1MTIyNzAx +MDE0NFowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD +VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n +IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g +IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqxf+DrDGaBtT8FK+n/ra+osTBLsBjzLZ +H49NzjaY2uQARIwo2BNEKqRrThckQpzTiKRBgtYj+4vJhuW5qYIF3PHeH+AMmVWY +8jjsbJ0gA8DvqqPGZARRLXgNo9KoOtYkTOmWehisEyMiG3zoMRGzXwmqMHBxRiVr +SXGAK5UBsh8CAwEAAaOCBEowggRGMB0GA1UdDgQWBBS4k/8uy9wsjqLnev42USGj +mFsMNDCCAUQGA1UdIwSCATswggE3gBS4k/8uy9wsjqLnev42USGjmFsMNKGCARqk +ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE +BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT +ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC +LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD +VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr +BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB +FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC +AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB +D2lwc0BtYWlsLmlwcy5lczBBBglghkgBhvhCAQ0ENBYyQ0xBU0UzIENBIENlcnRp +ZmljYXRlIGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgEC +BBwWGmh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDoGCWCGSAGG+EIBBAQtFito +dHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMuY3JsMD8GCWCG +SAGG+EIBAwQyFjBodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25D +TEFTRTMuaHRtbD8wPAYJYIZIAYb4QgEHBC8WLWh0dHA6Ly93d3cuaXBzLmVzL2lw +czIwMDIvcmVuZXdhbENMQVNFMy5odG1sPzA6BglghkgBhvhCAQgELRYraHR0cDov +L3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTMuaHRtbDBzBgNVHR8EbDBq +MDGgL6AthitodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMu +Y3JsMDWgM6Axhi9odHRwOi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy +Q0xBU0UzLmNybDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9v +Y3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQADgYEAF2VcmZVDAyevJuXr0LMXI/dD +qsfwfewPxqmurpYPdikc4gYtfibFPPqhwYHOU7BC0ZdXGhd+pFFhxu7pXu8Fuuu9 +D6eSb9ijBmgpjnn1/7/5p6/ksc7C0YBCJwUENPjDfxZ4IwwHJPJGR607VNCv1TGy +r33I6unUVtkOE7LFRVA= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES +MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU +V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz +WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO +LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE +AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH +K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX +RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z +rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx +3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq +hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC +MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls +XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D +lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn +aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ +YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDODCCAqGgAwIBAgIQQAWyU6AaRkNQCYGPEhB27DANBgkqhkiG9w0BAQUFADCB +zzELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJ +Q2FwZSBUb3duMRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3Rl +IFBlcnNvbmFsIFByZW1pdW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXBy +ZW1pdW1AdGhhd3RlLmNvbTAeFw05NjAxMDEwMDAwMDBaFw0yMTAxMDEyMzU5NTla +MIHPMQswCQYDVQQGEwJaQTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQH +EwlDYXBlIFRvd24xGjAYBgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQL +Ex9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3 +dGUgUGVyc29uYWwgUHJlbWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwt +cHJlbWl1bUB0aGF3dGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJ +Ztn4B0TPuYwu8KHvE0VsBd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O +0DI3lIi1DbbZ8/JE2dWIEt12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8f +AHB8Zs8QJQi6+u4A6UYDZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMB +Af8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBALpkCujztDHJJ2+idqAtNnHHhsAI +wk7t2pokGYf8WiOcck0I361cwzskgR1Xj7YSpSID7xK90S1elo8mJk9LG3w7oFIa +pag3hsRHKsrdQfho9cITQSma8AyozaH8FSMC23or1GJRQkfEox/00sVNVBDr2vDM +p083DL08yxDjGugV +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIH6jCCB1OgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl +SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl +SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 +DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAwNTkzOFoXDTI1MTIyNzAw +NTkzOFowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD +VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n +IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g +IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4FEnpwvdr9G5Q1uCN0VWcu+atsIS7ywS +zHb5BlmvXSHU0lq4oNTzav3KaY1mSPd05u42veiWkXWmcSjK5yISMmmwPh5r9FBS +YmL9Yzt9fuzuOOpi9GyocY3h6YvJP8a1zZRCb92CRTzo3wno7wpVqVZHYUxJZHMQ +KD/Kvwn/xi8CAwEAAaOCBEowggRGMB0GA1UdDgQWBBTrsxl588GlHKzcuh9morKb +adB4CDCCAUQGA1UdIwSCATswggE3gBTrsxl588GlHKzcuh9morKbadB4CKGCARqk +ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE +BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT +ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC +LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD +VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr +BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB +FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC +AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB +D2lwc0BtYWlsLmlwcy5lczBBBglghkgBhvhCAQ0ENBYyQ0xBU0UxIENBIENlcnRp +ZmljYXRlIGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgEC +BBwWGmh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDoGCWCGSAGG+EIBBAQtFito +dHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEuY3JsMD8GCWCG +SAGG+EIBAwQyFjBodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25D +TEFTRTEuaHRtbD8wPAYJYIZIAYb4QgEHBC8WLWh0dHA6Ly93d3cuaXBzLmVzL2lw +czIwMDIvcmVuZXdhbENMQVNFMS5odG1sPzA6BglghkgBhvhCAQgELRYraHR0cDov +L3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTEuaHRtbDBzBgNVHR8EbDBq +MDGgL6AthitodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEu +Y3JsMDWgM6Axhi9odHRwOi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy +Q0xBU0UxLmNybDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9v +Y3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQADgYEAK9Dr/drIyllq2tPMMi7JVBuK +Yn4VLenZMdMu9Ccj/1urxUq2ckCuU3T0vAW0xtnIyXf7t/k0f3gA+Nak5FI/LEpj +V4F1Wo7ojPsCwJTGKbqz3Bzosq/SLmJbGqmODszFV0VRFOlOHIilkfSj945RyKm+ +hjM+5i9Ibq9UkE6tsSU= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFVTCCBD2gAwIBAgIEO/OB0DANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQGEwJj +aDEOMAwGA1UEChMFYWRtaW4xETAPBgNVBAsTCFNlcnZpY2VzMSIwIAYDVQQLExlD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0aWVzMRYwFAYDVQQDEw1BZG1pbi1Sb290LUNB +MB4XDTAxMTExNTA4NTEwN1oXDTIxMTExMDA3NTEwN1owbDELMAkGA1UEBhMCY2gx +DjAMBgNVBAoTBWFkbWluMREwDwYDVQQLEwhTZXJ2aWNlczEiMCAGA1UECxMZQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdGllczEWMBQGA1UEAxMNQWRtaW4tUm9vdC1DQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMvgr0QUIv5qF0nyXZ3PXAJi +C4C5Wr+oVTN7oxIkXkxvO0GJToM9n7OVJjSmzBL0zJ2HXj0MDRcvhSY+KiZZc6Go +vDvr5Ua481l7ILFeQAFtumeza+vvxeL5Nd0Maga2miiacLNAKXbAcUYRa0Ov5VZB +++YcOYNNt/aisWbJqA2y8He+NsEgJzK5zNdayvYXQTZN+7tVgWOck16Da3+4FXdy +fH1NCWtZlebtMKtERtkVAaVbiWW24CjZKAiVfggjsiLo3yVMPGj3budLx5D9hEEm +vlyDOtcjebca+AcZglppWMX/iHIrx7740y0zd6cWEqiLIcZCrnpkr/KzwO135GkC +AwEAAaOCAf0wggH5MA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIASBkTCBjjCBiwYI +YIV0AREDAQAwfzArBggrBgEFBQcCAjAfGh1UaGlzIGlzIHRoZSBBZG1pbi1Sb290 +LUNBIENQUzBQBggrBgEFBQcCARZEaHR0cDovL3d3dy5pbmZvcm1hdGlrLmFkbWlu +LmNoL1BLSS9saW5rcy9DUFNfMl8xNl83NTZfMV8xN18zXzFfMC5wZGYwfwYDVR0f +BHgwdjB0oHKgcKRuMGwxFjAUBgNVBAMTDUFkbWluLVJvb3QtQ0ExIjAgBgNVBAsT +GUNlcnRpZmljYXRpb24gQXV0aG9yaXRpZXMxETAPBgNVBAsTCFNlcnZpY2VzMQ4w +DAYDVQQKEwVhZG1pbjELMAkGA1UEBhMCY2gwHQYDVR0OBBYEFIKf+iNzIPGXi7JM +Tb5CxX9mzWToMIGZBgNVHSMEgZEwgY6AFIKf+iNzIPGXi7JMTb5CxX9mzWTooXCk +bjBsMQswCQYDVQQGEwJjaDEOMAwGA1UEChMFYWRtaW4xETAPBgNVBAsTCFNlcnZp +Y2VzMSIwIAYDVQQLExlDZXJ0aWZpY2F0aW9uIEF1dGhvcml0aWVzMRYwFAYDVQQD +Ew1BZG1pbi1Sb290LUNBggQ784HQMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0B +AQUFAAOCAQEAeE96XCYRpy6umkPKXDWCRn7INo96ZrWpMggcDORuofHIwdTkgOeM +vWOxDN/yuT7CC3FAaUajbPRbDw0hRMcqKz0aC8CgwcyIyhw/rFK29mfNTG3EviP9 +QSsEbnelFnjpm1wjz4EaBiFjatwpUbI6+Zv3XbEt9QQXBn+c6DeFLe4xvC4B+MTr +a440xTk59pSYux8OHhEvqIwHCkiijGqZhTS3KmGFeBopaR+dJVBRBMoXwzk4B3Hn +0Zib1dEYFZa84vPJZyvxCbLOnPRDJgH6V2uQqbG+6DXVaf/wORVOvF/wzzv0viM/ +RWbEtJZdvo8N3sdtCULzifnxP/V0T9+4ZQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDOzCCAiOgAwIBAgIRANAeRlAAACmMAAAAAgAAAAIwDQYJKoZIhvcNAQEFBQAw +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYNDAeFw0wMDA5MTMwNjIyNTBaFw0yMDA5MTMwNjIyNTBa +MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UE +AxMORFNUIFJvb3QgQ0EgWDQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCthX3OFEYY8gSeIYur0O4ypOT68HnDrjLfIutL5PZHRwQGjzCPb9PFo/ihboJ8 +RvfGhBAqpQCo47zwYEhpWm1jB+L/OE/dBBiyn98krfU2NiBKSom2J58RBeAwHGEy +cO+lewyjVvbDDLUy4CheY059vfMjPAftCRXjqSZIolQb9FdPcAoa90mFwB7rKniE +J7vppdrUScSS0+eBrHSUPLdvwyn4RGp+lSwbWYcbg5EpSpE0GRJdchic0YDjvIoC +YHpe7Rkj93PYRTQyU4bhC88ck8tMqbvRYqMRqR+vobbkrj5LLCOQCHV5WEoxWh+0 +E2SpIFe7RkV++MmpIAc0h1tZAgMBAAGjMjAwMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFPCD6nPIP1ubWzdf9UyPWvf0hki9MA0GCSqGSIb3DQEBBQUAA4IBAQCE +G85wl5eEWd7adH6XW/ikGN5salvpq/Fix6yVTzE6CrhlP5LBdkf6kx1bSPL18M45 +g0rw2zA/MWOhJ3+S6U+BE0zPGCuu8YQaZibR7snm3HiHUaZNMu5c8D0x0bcMxDjY +AVVcHCoNiL53Q4PLW27nbY6wwG0ffFKmgV3blxrYWfuUDgGpyPwHwkfVFvz9qjaV +mf12VJffL6W8omBPtgteb6UaT/k1oJ7YI0ldGf+ngpVbRhD+LC3cUtT6GO/BEPZu +8YTV/hbiDH5v3khVqMIeKT6o8IuXGG7F6a6vKwP1F1FwTXf4UC/ivhme7vdUH7B/ +Vv4AEbT8dNfEeFxrkDbh +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns +YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH +MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y +aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe +Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX +MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj +IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx +KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM +HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw +DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC +AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji +nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX +rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn +jBJ7xUS0rg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFGjCCBAKgAwIBAgIEPL7eEDANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQ +TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu +dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBS +b290Q0EwHhcNMDIwNDE4MTQ1NDA4WhcNMjYwOTIxMTU0MjE5WjB2MQswCQYDVQQG +EwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMb +Q2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MSAwHgYDVQQDExdDQyBTaWduZXQg +LSBQQ0EgS2xhc2EgMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM7B +rBlbN5maM5eg0BOTqoZ+9NBDvU8Lm5rTdrMswFTCathzpVVLK/JD4K3+4oCZ9SRA +spEXE4gvwb08ASY6w5s+HpRkeJw8YzMFR5kDZD5adgnCAy4vDfIXYZgppXPaTQ8w +nfUZ7BZ7Zfa7QBemUIcJIzJBB0UqgtxWCeol9IekpBRVmuuSA6QG0Jkm+pGDJ05y +j2eQG8jTcBENM7sVA8rGRMyFA4skSZ+D0OG6FS2xC1i9JyN0ag1yII/LPx8HK5J4 +W9MaPRNjAEeaa2qI9EpchwrOxnyVbQfSedCG1VRJfAsE/9tT9CMUPZ3xW20QjQcS +ZJqVcmGW9gVsXKQOVLsCAwEAAaOCAbMwggGvMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMIIBBAYDVR0gBIH8MIH5MIH2Bg0rBgEEAb4/AgEKAQEBMIHk +MIGaBggrBgEFBQcCAjCBjRqBikNlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmll +IHogZG9rdW1lbnRlbTogIlBvbGl0eWthIENlcnR5ZmlrYWNqaSBkbGEgUm9vdENB +Ii4gQ2VydHlmaWthdCB3eXN0YXdpb255IHByemV6IFJvb3RDQSB3IGhpZXJhcmNo +aWkgQ0MgU2lnbmV0LjBFBggrBgEFBQcCARY5aHR0cDovL3d3dy5zaWduZXQucGwv +cmVwb3p5dG9yaXVtL2Rva3VtZW50eS9wY19yb290Y2EudHh0MEQGA1UdHwQ9MDsw +OaA3oDWGM2h0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9yb290Y2Ev +cm9vdGNhLmNybDAfBgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAdBgNV +HQ4EFgQUwGxGyl2CfpYHRonE82AVXO08kMIwDQYJKoZIhvcNAQEFBQADggEBABp1 +TAUsa+BeVWg4cjowc8yTJ5XN3GvN96GObMkxUGY7U9kVrLI71xBgoNVyzXTiMNDB +vjh7vdPWjpl5SDiRpnnKiOFXA43HvNWzUaOkTu1mxjJsZsanot1Xt6j0ZDC+03Fj +LHdYMyM9kSWp6afb4980EPYZCcSzgM5TOGfJmNii5Tq468VFKrX+52Aou1G22Ohu ++EEOlOrG7ylKv1hHUJJCjwN0ZVEIn1nDbrU9FeGCz8J9ihVUvnENEBbBkU37PWqW +uHitKQDVtcwTwJJdR8cmKq3NmkwAm9fPacidQLpaw0WkuGrS+fEDhu1Nhy9xELP6 +NA9GRTCNxm/dXlcwnmY= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIElTCCA/6gAwIBAgIEOJsRPDANBgkqhkiG9w0BAQQFADCBujEUMBIGA1UEChML +RW50cnVzdC5uZXQxPzA9BgNVBAsUNnd3dy5lbnRydXN0Lm5ldC9TU0xfQ1BTIGlu +Y29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDIwMDAg +RW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJl +IFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAyMDQxNzIwMDBa +Fw0yMDAyMDQxNzUwMDBaMIG6MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDE/MD0GA1UE +CxQ2d3d3LmVudHJ1c3QubmV0L1NTTF9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p +dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0Lm5ldCBMaW1pdGVk +MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHwV9OcfHO +8GCGD9JYf9Mzly0XonUwtZZkJi9ow0SrqHXmAGc0V55lxyKbc+bT3QgON1WqJUaB +bL3+qPZ1V1eMkGxKwz6LS0MKyRFWmponIpnPVZ5h2QLifLZ8OAfc439PmrkDQYC2 +dWcTC5/oVzbIXQA23mYU2m52H083jIITiQIDAQABo4IBpDCCAaAwEQYJYIZIAYb4 +QgEBBAQDAgAHMIHjBgNVHR8EgdswgdgwgdWggdKggc+kgcwwgckxFDASBgNVBAoT +C0VudHJ1c3QubmV0MT8wPQYDVQQLFDZ3d3cuZW50cnVzdC5uZXQvU1NMX0NQUyBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAyMDAw +IEVudHJ1c3QubmV0IExpbWl0ZWQxOjA4BgNVBAMTMUVudHJ1c3QubmV0IFNlY3Vy +ZSBTZXJ2ZXIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEw +KwYDVR0QBCQwIoAPMjAwMDAyMDQxNzIwMDBagQ8yMDIwMDIwNDE3NTAwMFowCwYD +VR0PBAQDAgEGMB8GA1UdIwQYMBaAFMtswGvjuz7L/CKc/vuLkpyw8m4iMB0GA1Ud +DgQWBBTLbMBr47s+y/winP77i5KcsPJuIjAMBgNVHRMEBTADAQH/MB0GCSqGSIb2 +fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQQFAAOBgQBi24GRzsia +d0Iv7L0no1MPUBvqTpLwqa+poLpIYcvvyQbvH9X07t9WLebKahlzqlO+krNQAraF +JnJj2HVQYnUUt7NQGj/KEQALhUVpbbalrlHhStyCP2yMNLJ3a9kC9n8O6mUE8c1U +yrrJzOCE98g+EZfTYAkYvAX/bIkz8OwVDw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo +YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 +MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy +NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G +A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA +A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 +Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s +QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV +eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 +B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh +z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T +AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i +ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w +TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH +MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD +VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE +VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh +bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B +AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM +bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi +ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG +VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c +ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ +AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50cnVzdC5u +ZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBsaW1pdHMgbGlh +Yi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBaMIHJMQswCQYDVQQGEwJVUzEU +MBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9D +bGllbnRfQ0FfSW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMq +RW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0G +CSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo +6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux +5zDeg7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zm +AqTmT173iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSC +ARkwggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50 +cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5m +by9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMp +IDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQg +Q2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCyg +KqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9DbGllbnQxLmNybDArBgNV +HRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkxMDEyMTkyNDMwWjALBgNVHQ8E +BAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW/O5bs8qZdIuV6kwwHQYDVR0OBBYE +FMT7nCl7l81MlvzuW7PKmXSLlepMMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA +BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7 +pFuPeJoSSJn59DXeDDYHAmsQOokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzz +wy5E97BnRqqS5TvaHBkUODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/a +EkP/TOYGJqibGapEPHayXOw= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy +aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s +IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp +Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV +BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp +Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g +Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU +J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO +JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY +wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o +koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN +qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E +Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe +xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u +7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU +sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI +sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP +cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9v +dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDAxMDExMTY0MTI4WhcNMjEwMTE0 +MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSww +KgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0G +A1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n13 +5zHCLielTWi5MbqNQ1mXx3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHE +SxP9cMIlrCL1dQu3U+SlK93OvRw6esP3E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4O +JgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5OEL8pahbSCOz6+MlsoCu +ltQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4jsNtlAHCE +AQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMB +AAGjYTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcB +CzAyMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRw +b2xpY3kwDQYJKoZIhvcNAQEFBQADggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo +7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrvm+0fazbuSCUlFLZWohDo7qd/ +0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0ROhPs7fpvcmR7 +nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx +x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ +33ZwmVxwQ023tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDtjCCAp6gAwIBAgIOBcAAAQACQdAGCk3OdRAwDQYJKoZIhvcNAQEFBQAwdjEL +MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV +BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDQgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 +Q2VudGVyIENsYXNzIDQgQ0EgSUkwHhcNMDYwMzIzMTQxMDIzWhcNMjUxMjMxMjI1 +OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i +SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgNCBDQTElMCMGA1UEAxMc +VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgNCBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBALXNTJytrlG7fEjFDSmGehSt2VA9CXIgDRS2Y8b+WJ7gIV7z +jyIZ3E6RIM1viCmis8GsKnK6i1S4QF/yqvhDhsIwXMynXX/GCEnkDjkvjhjWkd0j +FnmA22xIHbzB3ygQY9GB493fL3l1oht48pQB5hBiecugfQLANIJ7x8CtHUzXapZ2 +W78mhEj9h/aECqqSB5lIPGG8ToVYx5ct/YFKocabEvVCUNFkPologiJw3fX64yhC +L04y87OjNopq1mJcrPoBbbTgci6VaLTxkwzGioLSHVPqfOA/QrcSWrjN2qUGZ8uh +d32llvCSHmcOHUJG5vnt+0dTf1cERh9GX8eu4I8CAwEAAaNCMEAwDwYDVR0TAQH/ +BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFB/quz4lGwa9pd1iBX7G +TFq/6A9DMA0GCSqGSIb3DQEBBQUAA4IBAQBYpCubTPfkpJKknGWYGWIi/HIy6QRd +xMRwLVpG3kxHiiW5ot3u6hKvSI3vK2fbO8w0mCr3CEf/Iq978fTr4jgCMxh1KBue +dmWsiANy8jhHHYz1nwqIUxAUu4DlDLNdjRfuHhkcho0UZ3iMksseIUn3f9MYv5x5 ++F0IebWqak2SNmy8eesOPXmK2PajVnBd3ttPedJ60pVchidlvqDTB4FAVd0Qy+BL +iILAkH0457+W4Ze6mqtCD9Of2J4VMxHL94J59bXAQVaS4d9VA61Iz9PyLrHHLVZM +ZHQqMc7cdalUR6SnQnIJ5+ECpkeyBM1CE+FhDOB4OiIgohxgQoaH96Xm +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg +Q2xhc3MgMyBDQSAxMB4XDTA1MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzEL +MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD +VQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKxifZg +isRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//z +NIqeKNc0n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI ++MkcVyzwPX6UvCWThOiaAJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2R +hzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+ +mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0PAQH/BAQD +AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFP +Bdy7pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27s +EzNxZy5p+qksP2bAEllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2 +mSlf56oBzKwzqBwKu5HEA6BvtjT5htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yC +e/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQjel/wroQk5PMr+4okoyeYZdow +dXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIIDjCCBfagAwIBAgIJAOiOtsn4KhQoMA0GCSqGSIb3DQEBBQUAMIG8MQswCQYD VQQGEwJVUzEQMA4GA1UECBMHSW5kaWFuYTEVMBMGA1UEBxMMSW5kaWFuYXBvbGlz MSgwJgYDVQQKEx9Tb2Z0d2FyZSBpbiB0aGUgUHVibGljIEludGVyZXN0MRMwEQYD @@ -3253,85 +5363,211 @@ yaXG67Ljxay2oHA1u8hRadDytaIybrw/oDc5fHE2pgXfDBLkFqfF1stjo5VwP+YE o2A= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc -MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj -IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB -IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE -RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl -U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 -IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU -ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC -QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr -rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S -NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc -QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH -txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP -BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC -AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp -tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa -IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl -6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ -xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU -Cm26OWMohpLzGITY+9HPBVZkVw== +MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 +IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB +IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA +Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO +BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi +MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ +ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ +8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6 +zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y +fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7 +w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc +G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k +epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q +laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ +QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU +fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826 +YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w +ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY +gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe +MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0 +IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy +dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw +czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0 +dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl +aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC +AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg +b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB +ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc +nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg +18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c +gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl +Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY +sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T +SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF +CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum +GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk +zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW +omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIGJDCCBY2gAwIBAgIEQoaroDANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u -ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc -KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u -ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjA3 -MTQxNzEwMjhaFw0xNDA3MTQxNzQwMjhaMFwxCzAJBgNVBAYTAlVTMRUwEwYDVQQK -EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xGzAZBgNV -BAMTEkRpZ2lDZXJ0IEdsb2JhbCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAMQ8vMy66mLmnkIjr7SyEa5ijdmh04/MFHIZ7Zn2/d5du1nAsMKvaplS -lVcLNf/hhvqvosPBBWUnIHYvClQlfOor3ZVBV5sPO89H6AEGjMVESPwHLvNygzBR -lJ5pOoOph5AU2V7EoniPwT7UGWEOGufcGpUgQb5vF9q4HEHumLD61x01PxanBCgT -XT0FdZouhp4ssBeHIFhX7+HqVWC4LHAhrCljDBD8YLz51Rw3ZNW0+x6rJjlGiKTL -zTBnwCZ55cpo+SLX5dKxu0hMmwuYW0KS5dLtDkcw+t0nVmNqpQHHjq/wTjsbVRVE -1T5NVx7hkeq4oI/OOmNflom6CD7+RLsCAwEAAaOCAwUwggMBMBIGA1UdEwEB/wQI -MAYBAf8CAQAwggEyBgNVHSAEggEpMIIBJTCCASEGCSqGSIb2fQdLAjCCARIwJgYI -KwYBBQUHAgEWGmh0dHA6Ly93d3cuZW50cnVzdC5uZXQvY3BzMIHnBggrBgEFBQcC -AjCB2hqB10ZvciB1c2Ugc29sZWx5IHdpdGggU1NMIGFuZCBTL01JTUUgY2VydGlm -aWNhdGVzIGlzc3VlZCBieSBEaWdpY2VydCwgSW5jLiB0byBhdXRob3JpemVkIHN1 -YnNjcmliZXJzLg0KRE9FUyBOT1QgcmVwcmVzZW50IGFueSBlbmRvcnNlbWVudCBi -eSBFbnRydXN0IEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMgYXMgdG8gdGhlIGlkZW50 -aXR5IG9mIGFueSBjZXJ0aWZpY2F0ZSBob2xkZXIuMDEGA1UdJQQqMCgGCCsGAQUF -BwMBBggrBgEFBQcDAgYIKwYBBQUHAwQGCCsGAQUFBwMJMIIBGAYDVR0fBIIBDzCC -AQswKKAmoCSGImh0dHA6Ly9jcmwuZW50cnVzdC5uZXQvc2VydmVyMS5jcmwwgd6g -gduggdikgdUwgdIxCzAJBgNVBAYTAlVTMRQwEgYDVQQKEwtFbnRydXN0Lm5ldDE7 -MDkGA1UECxMyd3d3LmVudHJ1c3QubmV0L0NQUyBpbmNvcnAuIGJ5IHJlZi4gKGxp -bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0 -ZWQxOjA4BgNVBAMTMUVudHJ1c3QubmV0IFNlY3VyZSBTZXJ2ZXIgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEwCwYDVR0PBAQDAgEGMB8GA1Ud -IwQYMBaAFPAXYhNVPbP/CgBr+1CEl/PtYtAaMB0GA1UdDgQWBBSnxxOgegE8ne+C -SIJI1XNRthJWKjAZBgkqhkiG9n0HQQAEDDAKGwRWNy4xAwIAgTANBgkqhkiG9w0B -AQUFAAOBgQBK8bPOaGnjWKNh7bYWyJOxGDA+4HLfTz3iTeG4/D/ByeNFqV2pwdqj -5TbXjtYPrTavbLxE5ppGlKYRoNBS59pVsPYchftjUnu2mY8f4stHZKLrCGXmUdsc -S21/U58eDTGT1DBdHm4BBydgXbvT9ONsHSAPdSozEKe3idepFxQyAw== +MIID5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh +IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyOTA2MDAwMFoXDTM3MTEyMDE1 +MDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg +SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M +IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnej8Mlo2k06AX3dLm/WpcZuS+U +0pPlLYnKhHw/EEMbjIt8hFj4JHxIzyr9wBXZGH6EGhfT257XyuTZ16pYUYfw8ItI +TuLCxFlpMGK2MKKMCxGZYTVtfu/FsRkGIBKOQuHfD5YQUqjPnF+VFNivO3ULMSAf +RC+iYkGzuxgh28pxPIzstrkNn+9R7017EvILDOGsQI93f7DKeHEMXRZxcKLXwjqF +zQ6axOAAsNUl6twr5JQtOJyJQVdkKGUZHLZEtMgxa44Be3ZZJX8VHIQIfHNlIAqh +BC4aMqiaILGcLCFZ5/vP7nAtCMpjPiybkxlqpMKX/7eGV4iFbJ4VFitNLLMCAwEA +AaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoTYwFsuGkABFgFOxj8jY +PXy+XxIwHwYDVR0jBBgwFoAUoTYwFsuGkABFgFOxj8jYPXy+XxIwDgYDVR0PAQH/ +BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQCKIBilvrMvtKaEAEAwKfq0FHNMeUWn +9nDg6H5kHgqVfGphwu9OH77/yZkfB2FK4V1Mza3u0FIy2VkyvNp5ctZ7CegCgTXT +Ct8RHcl5oIBN/lrXVtbtDyqvpxh1MwzqwWEFT2qaifKNuZ8u77BfWgDrvq2g+EQF +Z7zLBO+eZMXpyD8Fv8YvBxzDNnGGyjhmSs3WuEvGbKeXO/oTLW4jYYehY0KswsuX +n2Fozy1MBJ3XJU8KDk2QixhWqJNIV9xvrr2eZ1d3iVCzvhGbRWeDhhmH05i9CBoW +H1iCC+GWaQVLjuyDUTEH1dSf/1l7qG6Fz9NLqUmwX7A5KGgOc90lmt4S -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEUDCCA7mgAwIBAgIJAN4ppNGwj6yIMA0GCSqGSIb3DQEBBAUAMIHMMQswCQYD -VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j -aXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5jLjEpMCcGA1UECxMgTGluZGVu -IExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAnBgNVBAMTIExpbmRlbiBMYWIg -Q2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZIhvcNAQkBFhBjYUBsaW5kZW5s -YWIuY29tMB4XDTA1MDQyMTAyNDAzMVoXDTI1MDQxNjAyNDAzMVowgcwxCzAJBgNV -BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp -c2NvMRkwFwYDVQQKExBMaW5kZW4gTGFiLCBJbmMuMSkwJwYDVQQLEyBMaW5kZW4g -TGFiIENlcnRpZmljYXRlIEF1dGhvcml0eTEpMCcGA1UEAxMgTGluZGVuIExhYiBD -ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgkqhkiG9w0BCQEWEGNhQGxpbmRlbmxh -Yi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKXh1MThucdTbMg9bYBO -rAm8yWns32YojB0PRfbq8rUjepEhTm3/13s0u399Uc202v4ejcGhkIDWJZd2NZMF -oKrhmRfxGHSKPCuFaXC3jh0lRECj7k8FoPkcmaPjSyodrDFDUUuv+C06oYJoI+rk -8REyal9NwgHvqCzOrZtiTXAdAgMBAAGjggE2MIIBMjAdBgNVHQ4EFgQUO1zK2e1f -1wO1fHAjq6DTJobKDrcwggEBBgNVHSMEgfkwgfaAFDtcytntX9cDtXxwI6ug0yaG -yg63oYHSpIHPMIHMMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW -MBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5j -LjEpMCcGA1UECxMgTGluZGVuIExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAn -BgNVBAMTIExpbmRlbiBMYWIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZI -hvcNAQkBFhBjYUBsaW5kZW5sYWIuY29tggkA3imk0bCPrIgwDAYDVR0TBAUwAwEB -/zANBgkqhkiG9w0BAQQFAAOBgQA/ZkgfvwHYqk1UIAKZS3kMCxz0HvYuEQtviwnu -xA39CIJ65Zozs28Eg1aV9/Y+Of7TnWhW+U3J3/wD/GghaAGiKK6vMn9gJBIdBX/9 -e6ef37VGyiOEFFjnUIbuk0RWty0orN76q/lI/xjCi15XSA/VSq2j4vmnwfZcPTDu -glmQ1A== +MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT +MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0 +aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw +WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE +AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m +OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu +T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c +JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR +Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz +PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm +aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM +TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g +LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO +BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv +dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB +AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL +NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W +b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp +ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow +fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV +BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM +cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S +HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 +CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk +3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz +6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV +HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud +EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv +Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw +Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww +DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 +5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj +Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI +gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ +aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl +izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy +NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY +dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 +WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS +v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v +UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu +IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC +W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFFjCCBH+gAwIBAgIBADANBgkqhkiG9w0BAQQFADCBsDELMAkGA1UEBhMCSUwx +DzANBgNVBAgTBklzcmFlbDEOMAwGA1UEBxMFRWlsYXQxFjAUBgNVBAoTDVN0YXJ0 +Q29tIEx0ZC4xGjAYBgNVBAsTEUNBIEF1dGhvcml0eSBEZXAuMSkwJwYDVQQDEyBG +cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYS +YWRtaW5Ac3RhcnRjb20ub3JnMB4XDTA1MDMxNzE3Mzc0OFoXDTM1MDMxMDE3Mzc0 +OFowgbAxCzAJBgNVBAYTAklMMQ8wDQYDVQQIEwZJc3JhZWwxDjAMBgNVBAcTBUVp +bGF0MRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMRowGAYDVQQLExFDQSBBdXRob3Jp +dHkgRGVwLjEpMCcGA1UEAxMgRnJlZSBTU0wgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkxITAfBgkqhkiG9w0BCQEWEmFkbWluQHN0YXJ0Y29tLm9yZzCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEA7YRgACOeyEpRKSfeOqE5tWmrCbIvNP1h3D3TsM+x +18LEwrHkllbEvqoUDufMOlDIOmKdw6OsWXuO7lUaHEe+o5c5s7XvIywI6Nivcy+5 +yYPo7QAPyHWlLzRMGOh2iCNJitu27Wjaw7ViKUylS7eYtAkUEKD4/mJ2IhULpNYI +LzUCAwEAAaOCAjwwggI4MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgHmMB0G +A1UdDgQWBBQcicOWzL3+MtUNjIExtpidjShkjTCB3QYDVR0jBIHVMIHSgBQcicOW +zL3+MtUNjIExtpidjShkjaGBtqSBszCBsDELMAkGA1UEBhMCSUwxDzANBgNVBAgT +BklzcmFlbDEOMAwGA1UEBxMFRWlsYXQxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4x +GjAYBgNVBAsTEUNBIEF1dGhvcml0eSBEZXAuMSkwJwYDVQQDEyBGcmVlIFNTTCBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYSYWRtaW5Ac3Rh +cnRjb20ub3JnggEAMB0GA1UdEQQWMBSBEmFkbWluQHN0YXJ0Y29tLm9yZzAdBgNV +HRIEFjAUgRJhZG1pbkBzdGFydGNvbS5vcmcwEQYJYIZIAYb4QgEBBAQDAgAHMC8G +CWCGSAGG+EIBDQQiFiBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAy +BglghkgBhvhCAQQEJRYjaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL2NhLWNybC5j +cmwwKAYJYIZIAYb4QgECBBsWGWh0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy8wOQYJ +YIZIAYb4QgEIBCwWKmh0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9pbmRleC5waHA/ +YXBwPTExMTANBgkqhkiG9w0BAQQFAAOBgQBscSXhnjSRIe/bbL0BCFaPiNhBOlP1 +ct8nV0t2hPdopP7rPwl+KLhX6h/BquL/lp9JmeaylXOWxkjHXo0Hclb4g4+fd68p +00UOpO6wNnQt8M2YI3s3S9r+UZjEHjQ8iP2ZO1CnwYszx8JSFhKVU2Ui77qLzmLb +cCOxgN8aIDjnfg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcN +AQkBFglwa2lAc2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZp +dHNlZXJpbWlza2Vza3VzMRAwDgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMw +MVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMQsw +CQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEQ +MA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOB +SvZiF3tfTQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkz +ABpTpyHhOEvWgxutr2TC+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvH +LCu3GFH+4Hv2qEivbDtPL+/40UceJlfwUR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMP +PbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDaTpxt4brNj3pssAki14sL +2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQFMAMBAf8w +ggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwIC +MIHDHoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDk +AGwAagBhAHMAdABhAHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0 +AHMAZQBlAHIAaQBtAGkAcwBrAGUAcwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABz +AGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABrAGkAbgBuAGkAdABhAG0AaQBz +AGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nwcy8wKwYDVR0f +BCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE +FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcY +P2/v6X2+MA4GA1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOi +CfP+JmeaUOTDBS8rNXiRTHyoERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+g +kcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyLabVAyJRld/JXIWY7zoVAtjNjGr95 +HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678IIbsSt4beDI3poHS +na9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkhMp6q +qIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0Z +TbvGRNs2yyqcjg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJO +TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEy +MTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVk +ZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENB +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFtvszn +ExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw71 +9tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MO +hXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U +tFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3o +BmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAh +SQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDww +OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMv +cm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA +7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k +/rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzm +eafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0C5GUR5z6 +u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy +7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR +iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== -----END CERTIFICATE----- diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index 455dc9e88..b264e08e3 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -10,10 +10,11 @@ state Keyword to indicate state block or state transition integer Integer type float Floating-point type string String type -key Key type. Use NULL_KEY to test for empty keys. +key Key type. Use NULL_KEY to test for empty keys vector Vector type of 3 floats. Used to represent 3D motion, Euler angles, and color.:Access components by .x, .y. or .z rotation Rotation type of 4 floats. Used to represent rotation.:Access components by .x, .y., .z, or .w list List of various data types +quaternion Rotation type of 4 floats. Used to represent rotation.:Access components by .x, .y, .z, or .w # events [word 0, .3, .5] @@ -28,7 +29,7 @@ collision_end collision_end(integer num_detected):Triggered when task stops coll land_collision_start land_collision_start(vector pos):Triggered when task starts colliding with land land_collision land_collision(vector pos):Triggered when task is colliding with land land_collision_end land_collision_end(vector pos):Triggered when task stops colliding with land -timer timer():Result of the llSetTimerEvent library function call. +timer timer():Result of the llSetTimerEvent library function call listen listen(integer channel, string name, key id, string message):Result of the llListen library function call sensor sensor(integer num_detected):Result of the llSensor library function call no_sensor no_sensor():Result of the llSensor library function call @@ -44,13 +45,15 @@ attach attach(key id):Triggered when task attaches or detaches from agent dataserver dataserver(key queryid, string data):Triggered when task receives asynchronous data moving_start moving_start():Triggered when task begins moving moving_end moving_end():Triggered when task stops moving -on_rez on_rez(integer start_param):Triggered when task is rezed in from inventory or another task -object_rez object_rez(key id):Triggered when task rezes in another task +on_rez on_rez(integer start_param):Triggered when task is rezzed in from inventory or another task +object_rez object_rez(key id):Triggered when task rezzes in another task link_message link_message(integer sender_num, integer num, string str, key id):Triggered when task receives a link message via LLMessageLinked library function call changed changed( integer change ):Triggered various event change the task:(test change with CHANGED_INVENTORY, CHANGED_COLOR, CHANGED_SHAPE, CHANGED_SCALE, CHANGED_TEXTURE, CHANGED_LINK, CHANGED_ALLOWED_DROP, CHANGED_OWNER, CHANGED_REGION, CHANGED_TELEPORT, CHANGED_REGION_START, CHANGED_MEDIA) remote_data remote_data(integer event_type, key channel, key message_id, string sender,integer idata, string sdata):Triggered by various XML-RPC calls (event_type will be one of REMOTE_DATA_CHANNEL, REMOTE_DATA_REQUEST, REMOTE_DATA_REPLY) http_response http_response(key request_id, integer status, list metadata, string body):Triggered when task receives a response to one of its llHTTPRequests http_request http_request(key id, string method, string body):Triggered when task receives an http request against a public URL +transaction_result transaction_result(key id, integer success, string data):Triggered when task receives asynchronous data. +path_update path_update(integer type, list reserved):Triggered when the state of a pathfinder character changes. Note; "list reserved" is not currently used # integer constants [word .1, .1, .5] @@ -63,6 +66,7 @@ STATUS_ROTATE_Y Passed in the llSetStatus library function. If FALSE, object do STATUS_ROTATE_Z Passed in the llSetStatus library function. If FALSE, object doesn't rotate around local Z axis STATUS_SANDBOX Passed in the llSetStatus library function. If TRUE, object can't cross region boundaries or move more than 10 meters from its start location STATUS_BLOCK_GRAB Passed in the llSetStatus library function. If TRUE, object can't be grabbed and physically dragged +STATUS_BLOCK_GRAB_OBJECT This status flag keeps the object from being moved by grabs. This flag applies to the entire linkset STATUS_DIE_AT_EDGE Passed in the llSetStatus library function. If TRUE, objects that reach the edge of the world just die:rather than teleporting back to the owner STATUS_RETURN_AT_EDGE Passed in the llSetStatus library function. If TRUE, script rezzed objects that reach the edge of the world:are returned rather than killed:STATUS_RETURN_AT_EDGE trumps STATUS_DIE_AT_EDGE if both are set STATUS_CAST_SHADOWS Passed in the llSetStatus library function. If TRUE, object casts shadows on other objects @@ -93,6 +97,7 @@ PERMISSION_CHANGE_LINKS Passed to llRequestPermissions library function to req # PERMISSION_CHANGE_PERMISSIONS Passed to llRequestPermissions library function to request permission to change permissions PERMISSION_TRACK_CAMERA Passed to llRequestPermissions library function to request permission to track agent's camera PERMISSION_CONTROL_CAMERA Passed to llRequestPermissions library function to request permission to change agent's camera +PERMISSION_TELEPORT Passed to llRequestPermissions library function to request permission to teleport agent DEBUG_CHANNEL Chat channel reserved for debug and error messages from scripts PUBLIC_CHANNEL Chat channel that broadcasts to all nearby users @@ -112,6 +117,10 @@ AGENT_BUSY Returned by llGetAgentInfo if the Agent is busy AGENT_ALWAYS_RUN Returned by llGetAgentInfo if the Agent has 'Always Run' enabled AGENT_AUTOPILOT Returned by llGetAgentInfo if the Agent is under autopilot control +AGENT_LIST_PARCEL Passed to llGetAgentList to return only agents on the same parcel where the script is running +AGENT_LIST_PARCEL_OWNER Passed to llGetAgentList to return only agents on any parcel in the region where the parcel owner is the same as the owner of the parcel under the scripted object +AGENT_LIST_REGION Passed to llGetAgentList to return any/all agents in the region + PSYS_PART_FLAGS PSYS_PART_START_COLOR PSYS_PART_START_ALPHA @@ -153,27 +162,31 @@ PSYS_SRC_PATTERN_ANGLE PSYS_SRC_PATTERN_ANGLE_CONE PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY -OBJECT_UNKNOWN_DETAIL Returned by llGetObjectDetails when passed an invalid object parameter type. -OBJECT_NAME Used with llGetObjectDetails to get an object's name. -OBJECT_DESC Used with llGetObjectDetails to get an object's description. -OBJECT_POS Used with llGetObjectDetails to get an object's position. -OBJECT_ROT Used with llGetObjectDetails to get an object's rotation. -OBJECT_VELOCITY Used with llGetObjectDetails to get an object's velocity. -OBJECT_OWNER Used with llGetObjectDetails to get an object's owner's key. Will be NULL_KEY if group owned. -OBJECT_GROUP Used with llGetObjectDetails to get an object's group's key. -OBJECT_CREATOR Used with llGetObjectDetails to get an object's creator's key. +OBJECT_UNKNOWN_DETAIL Returned by llGetObjectDetails when passed an invalid object parameter type +OBJECT_NAME Used with llGetObjectDetails to get an object's name +OBJECT_DESC Used with llGetObjectDetails to get an object's description +OBJECT_POS Used with llGetObjectDetails to get an object's position +OBJECT_ROT Used with llGetObjectDetails to get an object's rotation +OBJECT_VELOCITY Used with llGetObjectDetails to get an object's velocity +OBJECT_OWNER Used with llGetObjectDetails to get an object's owner's key. Will be NULL_KEY if group owned +OBJECT_GROUP Used with llGetObjectDetails to get an object's group's key +OBJECT_CREATOR Used with llGetObjectDetails to get an object's creator's key OBJECT_RUNNING_SCRIPT_COUNT Used with llGetObjectDetails to get an object's velocity. OBJECT_TOTAL_SCRIPT_COUNT Used with llGetObjectDetails to get an object's owner's key. Will be NULL_KEY if group owned. OBJECT_SCRIPT_MEMORY Used with llGetObjectDetails to get an object's group's key. OBJECT_SCRIPT_TIME Used with llGetObjectDetails to get an object's creator's key. +OBJECT_PRIM_EQUIVALENCE Gets the prim equivalence of the object. +OBJECT_SERVER_COST Used with llGetObjectDetails to get the server cost. +OBJECT_STREAMING_COST Used with llGetObjectDetails to get the streaming (download) cost. +OBJECT_PHYSICS_COST Used with llGetObjectDetails to get the physics cost. # some vehicle params -VEHICLE_TYPE_NONE -VEHICLE_TYPE_SLED -VEHICLE_TYPE_CAR -VEHICLE_TYPE_BOAT -VEHICLE_TYPE_AIRPLANE -VEHICLE_TYPE_BALLOON +VEHICLE_TYPE_NONE Used with llSetVehicleType to turn off vehicle support +VEHICLE_TYPE_SLED Used with llSetVehicleType to make a simple vehicle that bumps along the ground, and likes to move along its local x-axis +VEHICLE_TYPE_CAR Used with llSetVehicleType to make a vehicle that bounces along the ground but needs the motors to be driven from external controls or timer events +VEHICLE_TYPE_BOAT Used with llSetVehicleType to make a vehicle that hovers over water with lots of friction and some angular deflection +VEHICLE_TYPE_AIRPLANE Used with llSetVehicleType to make a vehicle that uses linear deflection for lift, and banking to turn, but doesn't hover +VEHICLE_TYPE_BALLOON Used with llSetVehicleType to make a vehicle that uses hover, and friction, but doesn't use deflection VEHICLE_REFERENCE_FRAME Rotation of vehicle axes relative to local frame @@ -204,7 +217,7 @@ VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY A slider between 0 (bouncy) and 1 (critic VEHICLE_VERTICAL_ATTRACTION_TIMESCALE The exponential timescale for the vehicle to align its z-axis to the world z-axis (vertical) VEHICLE_BANKING_EFFICIENCY A slider between -1 (leans out of turns), 0 (no banking), and +1 (leans into turns) -VEHICLE_BANKING_MIX A slider betwen 0 (static banking) and 1 (dynamic banking) +VEHICLE_BANKING_MIX A slider between 0 (static banking) and 1 (dynamic banking) VEHICLE_BANKING_TIMESCALE The exponential timescale for the banking behavior to take full effect VEHICLE_FLAG_NO_DEFLECTION_UP Prevents linear deflection along world-z axis @@ -214,9 +227,9 @@ VEHICLE_FLAG_HOVER_TERRAIN_ONLY Hover only pays attention to terrain height VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT Hover only pays attention to global height VEHICLE_FLAG_HOVER_UP_ONLY Hover only pushes up VEHICLE_FLAG_LIMIT_MOTOR_UP Prevents ground vehicles from motoring into the sky -VEHICLE_FLAG_MOUSELOOK_STEER Makes vehicle try to turn toward mouselook direction. -VEHICLE_FLAG_MOUSELOOK_BANK Makes vehicle try to turn toward mouselook direction assuming banking is enabled. -VEHICLE_FLAG_CAMERA_DECOUPLED Causes the camera look-at axis to NOT move when the vehicle rotates. +VEHICLE_FLAG_MOUSELOOK_STEER Makes vehicle try to turn toward mouselook direction +VEHICLE_FLAG_MOUSELOOK_BANK Makes vehicle try to turn toward mouselook direction assuming banking is enabled +VEHICLE_FLAG_CAMERA_DECOUPLED Causes the camera look-at axis to NOT move when the vehicle rotates CAMERA_PITCH (-45 to 80) (Adjusts the angular amount that the camera aims straight ahead vs. straight down, maintaining the same distance. Analogous to 'incidence'.") CAMERA_FOCUS_OFFSET (-10 to 10) A vector that adjusts the position of the camera focus position relative to the subject @@ -244,7 +257,7 @@ INVENTORY_BODYPART Passed to task inventory library functions to reference body INVENTORY_ANIMATION Passed to task inventory library functions to reference animations INVENTORY_GESTURE Passed to task inventory library functions to reference gestures INVENTORY_ALL Passed to task inventory library functions to reference all inventory items -INVENTORY_NONE Returned by llGetInventoryType when no item is found. +INVENTORY_NONE Returned by llGetInventoryType when no item is found ATTACH_CHEST Passed to llAttachToAvatar to attach task to chest ATTACH_HEAD Passed to llAttachToAvatar to attach task to head @@ -262,7 +275,7 @@ ATTACH_LEAR Passed to llAttachToAvatar to attach task to left ear ATTACH_REAR Passed to llAttachToAvatar to attach task to right ear ATTACH_LEYE Passed to llAttachToAvatar to attach task to left eye ATTACH_REYE Passed to llAttachToAvatar to attach task to right eye -ATTACH_NOSE Passed to llAttachToAvatar to attach task to noce +ATTACH_NOSE Passed to llAttachToAvatar to attach task to nose ATTACH_RUARM Passed to llAttachToAvatar to attach task to right upper arm ATTACH_RLARM Passed to llAttachToAvatar to attach task to right lower arm ATTACH_LUARM Passed to llAttachToAvatar to attach task to left upper arm @@ -274,8 +287,19 @@ ATTACH_LHIP Passed to llAttachToAvatar to attach task to left hip ATTACH_LULEG Passed to llAttachToAvatar to attach task to left upper leg ATTACH_LLLEG Passed to llAttachToAvatar to attach task to left lower leg ATTACH_BELLY Passed to llAttachToAvatar to attach task to belly -ATTACH_RPEC Passed to llAttachToAvatar to attach task to right pectoral -ATTACH_LPEC Passed to llAttachToAvatar to attach task to left pectoral +ATTACH_LEFT_PEC Passed to llAttachToAvatar to attach task to left pectoral +ATTACH_RIGHT_PEC Passed to llAttachToAvatar to attach task to right pectoral +ATTACH_HUD_CENTER_2 Passed to llAttachToAvatar to attach task to center 2 hud area +ATTACH_HUD_TOP_RIGHT Passed to llAttachToAvatar to attach task to top right hud area +ATTACH_HUD_TOP_CENTER Passed to llAttachToAvatar to attach task to top center hud area +ATTACH_HUD_TOP_LEFT Passed to llAttachToAvatar to attach task to top left hud area +ATTACH_HUD_CENTER_1 Passed to llAttachToAvatar to attach task to center 1 hud area +ATTACH_HUD_BOTTOM_LEFT Passed to llAttachToAvatar to attach task to bottom left hud area +ATTACH_HUD_BOTTOM Passed to llAttachToAvatar to attach task to bottom hud area +ATTACH_HUD_BOTTOM_RIGHT Passed to llAttachToAvatar to attach task to bottom right hud area +##The following attachment points exist only as numbers thus far, but will be ready when the time comes. +#ATTACH_NECK Passed to llAttachToAvatar to attach task to neck +#ATTACH_ROOT Passed to llAttachToAvatar to attach task to avatar center/root LAND_LEVEL Passed to llModifyLand to level terrain LAND_RAISE Passed to llModifyLand to raise terrain @@ -302,7 +326,7 @@ PAYMENT_INFO_USED Used with llRequestAgentData to tell if Agent is of "Payment I ANIM_ON Enable texture animation LOOP Loop when animating textures REVERSE Animate in the reverse direction -PING_PONG Animate forward, then reverse. +PING_PONG Animate forward, then reverse SMOOTH Textures slides, instead of stepping ROTATE Rotates the texture, instead of using frames SCALE Scales the texture, instead of using frames @@ -342,26 +366,35 @@ REMOTE_DATA_REQUEST Value of event_type in remote_event if XML-RPC request is re REMOTE_DATA_REPLY Value of event_type in remote_event if XML-RPC reply is received +PRIM_NAME For primitive name (from server v1.40 onwards). Followed by a string. +PRIM_DESC For primitive description (from server v1.40 onwards). Followed by a string. PRIM_TYPE Followed by PRIM_TYPE_BOX, PRIM_TYPE_CYLINDER, PRIM_TYPE_PRISM, PRIM_TYPE_SPHERE, PRIM_TYPE_TORUS, PRIM_TYPE_TUBE, or PRIM_TYPE_SCULPT and their arguments +PRIM_SLICE Get and set the 'slice' parameter of all shapes. Takes a vector parameter of the form +PRIM_PHYSICS_SHAPE_TYPE For primitive physics shape type. Followed with either PRIM_PHYSICS_SHAPE_PRIM, PRIM_PHYSICS_SHAPE_NONE or PRIM_PHYSICS_SHAPE_CONVEX. PRIM_MATERIAL Followed by PRIM_MATERIAL_STONE, PRIM_MATERIAL_METAL, PRIM_MATERIAL_GLASS, PRIM_MATERIAL_WOOD, PRIM_MATERIAL_FLESH, PRIM_MATERIAL_PLASTIC, or PRIM_MATERIAL_RUBBER PRIM_PHYSICS Sets physics to TRUE or FALSE PRIM_FLEXIBLE Followed by TRUE or FALSE, integer softness, float gravity, float friction, float wind, float tension, and vector force PRIM_POINT_LIGHT Followed by TRUE or FALSE, vector color, float intensity, float radius, float falloff PRIM_TEMP_ON_REZ Sets temporay on rez to TRUE or FALSE PRIM_PHANTOM Sets phantom to TRUE or FALSE -PRIM_CAST_SHADOWS DEPRECATED. Takes 1 parameter, an integer, but has no effect when set and always returns 0 if used in llGetPrimitiveParams. +PRIM_CAST_SHADOWS DEPRECATED. Takes 1 parameter, an integer, but has no effect when set and always returns 0 if used in llGetPrimitiveParams PRIM_POSITION Sets primitive position to a vector position +PRIM_POS_LOCAL Sets the prim's local position PRIM_SIZE Sets primitive size to a vector size PRIM_ROTATION Sets primitive rotation +PRIM_ROT_LOCAL Sets the prim's local rotation PRIM_TEXTURE Followed by an integer face, key id, vector repeats, vector offsets,:and float rotation in radians +PRIM_TEXT For primitive hovertext. Followed by a string, a vector color and a float alpha PRIM_COLOR Followed by an integer face, vector color, and float alpha PRIM_BUMP_SHINY Followed by an integer face, one of PRIM_SHINY_NONE, PRIM_SHINY_LOW,:PRIM_SHINY_MEDIUM, or PRIM_SHINY_HIGH,:and one of PRIM_BUMP_NONE, PRIM_BUMP_BRIGHT, PRIM_BUMP_DARK, etc PRIM_FULLBRIGHT Followed by an integer face, and TRUE or FALSE PRIM_TEXGEN Followed by an integer face, and one of PRIM_TEXGEN_DEFAULT or PRIM_TEXGEN_PLANAR PRIM_GLOW Followed by an integer face, and a float from 0.0 to 1.0 specifying glow amount -PRIM_TEXT For primitive hovertext. Followed by a string, a vector color and a float alpha -PRIM_NAME For primitive name (from server v1.40 onwards). Followed by a string. -PRIM_DESC For primitive description (from server v1.40 onwards). Followed by a string. +PRIM_OMEGA Makes the object spin at the specified axis and rate +PRIM_LINK_TARGET Used to get or set multiple links with a single PrimParameters call + +PROFILE_NONE Disables profiling +PROFILE_SCRIPT_MEMORY Enables memory profiling PRIM_TYPE_BOX Followed by integer hole shape, vector cut, float hollow, vector twist,:vector top size, and vector top shear PRIM_TYPE_CYLINDER Followed by integer hole shape, vector cut, float hollow, vector twist,:vector top size, and vector top shear @@ -372,10 +405,10 @@ PRIM_TYPE_TUBE Followed by integer hole shape, vector cut, float hollow, vector PRIM_TYPE_RING Followed by integer hole shape, vector cut, float hollow, vector twist,:vector hole size, vector top shear, vector advanced cut, vector taper,:float revolutions, float radius offset, and float skew PRIM_TYPE_SCULPT Followed by a key/string texture uuid, and one of PRIM_SCULPT_TYPE_SPHERE, PRIM_SCULPT_TYPE_TORUS, PRIM_SCULPT_TYPE_PLANE, or PRIM_SCULPT_TYPE_CYLINDER -PRIM_HOLE_DEFAULT Sets hole type to match the prim type. -PRIM_HOLE_SQUARE Sets hole type to square. -PRIM_HOLE_CIRCLE Sets hole type to circle. -PRIM_HOLE_TRIANGLE Sets hole type to triangle. +PRIM_HOLE_DEFAULT Sets hole type to match the prim type +PRIM_HOLE_SQUARE Sets hole type to square +PRIM_HOLE_CIRCLE Sets hole type to circle +PRIM_HOLE_TRIANGLE Sets hole type to triangle PRIM_MATERIAL_STONE Sets material to stone PRIM_MATERIAL_METAL Sets material to metal @@ -421,6 +454,10 @@ PRIM_SCULPT_TYPE_MASK Mask used to determine stitching type PRIM_SCULPT_FLAG_INVERT Flag to specify that the surface normals should be inverted PRIM_SCULPT_FLAG_MIRROR Flag to specify that the prim should be reflected along X axis +PRIM_PHYSICS_SHAPE_PRIM Use the normal prim shape for physics (this is the default for all non-mesh objects) +PRIM_PHYSICS_SHAPE_CONVEX Ignore this prim in the physics shape. This cannot be applied to the root prim. +PRIM_PHYSICS_SHAPE_NONE Use the convex hull of the prim shape for physics (this is the default for mesh objects) + MASK_BASE Base permissions MASK_OWNER Owner permissions MASK_GROUP Group permissions @@ -437,6 +474,7 @@ PARCEL_MEDIA_COMMAND_STOP Stop media stream PARCEL_MEDIA_COMMAND_PAUSE Pause media stream PARCEL_MEDIA_COMMAND_PLAY Play media stream PARCEL_MEDIA_COMMAND_LOOP Loop media stream +PARCEL_MEDIA_COMMAND_LOOP_SET Used to get or set the parcel's media loop duration PARCEL_MEDIA_COMMAND_TEXTURE Get or set the parcel's media texture PARCEL_MEDIA_COMMAND_URL Get or set the parcel's media url PARCEL_MEDIA_COMMAND_TYPE Get or set the parcel's media mimetype @@ -445,7 +483,7 @@ PARCEL_MEDIA_COMMAND_TIME Set media stream to specific time PARCEL_MEDIA_COMMAND_SIZE Get or set the parcel's media pixel resolution PARCEL_MEDIA_COMMAND_AGENT Allows media stream commands to apply to only one agent PARCEL_MEDIA_COMMAND_UNLOAD Unloads the media stream -PARCEL_MEDIA_COMMAND_AUTO_ALIGN Auto aligns the media stream to the texture size. May cause a performance hit and loss of some visual quality. +PARCEL_MEDIA_COMMAND_AUTO_ALIGN Auto aligns the media stream to the texture size. May cause a performance hit and loss of some visual quality PAY_HIDE Used with llSetPayPrice to hide a button PAY_DEFAULT Used with llSetPayPrice to use the default price for a button @@ -488,11 +526,19 @@ REGION_FLAG_BLOCK_FLY Used with llGetRegionFlags to find if a region blocks f REGION_FLAG_ALLOW_DIRECT_TELEPORT Used with llGetRegionFlags to find if a region allows direct teleports REGION_FLAG_RESTRICT_PUSHOBJECT Used with llGetRegionFlags to find if a region restricts llPushObject() calls -HTTP_METHOD Used with llHTTPRequest to specify the method, such as "GET" or "POST" +ESTATE_ACCESS_ALLOWED_AGENT_ADD Used with llManageEstateAccess to add an agent to this estate's allowed residents list. +ESTATE_ACCESS_ALLOWED_AGENT_REMOVE Used with llManageEstateAccess to remove an agent from this estate's allowed residents list. +ESTATE_ACCESS_ALLOWED_GROUP_ADD Used with llManageEstateAccess to add a group to this estate's allowed groups list. +ESTATE_ACCESS_ALLOWED_GROUP_REMOVE Used with llManageEstateAccess to remove a group from this estate's allowed groups list. +ESTATE_ACCESS_BANNED_AGENT_ADD Used with llManageEstateAccess to add an agent to this estate's banned residents list. +ESTATE_ACCESS_BANNED_AGENT_REMOVE Used with llManageEstateAccess to remove an agent from this estate's banned residents list. + +HTTP_METHOD Used with llHTTPRequest to specify the method, "GET", "POST", "PUT", or "DELETE" HTTP_MIMETYPE Used with llHTTPRequest to specify the MIME type, defaults to "text/plain" -HTTP_BODY_MAXLENGTH Used with llHTTPRequest to specify the maxium reponse body to return +HTTP_BODY_MAXLENGTH Used with llHTTPRequest to specify the maximum response body to return HTTP_VERIFY_CERT Used with llHTTPRequest to specify SSL certificate verification HTTP_BODY_TRUNCATED Used with http_response to indicate truncation point in bytes +HTTP_VERBOSE_THROTTLE Used with llHTTPRequest to shout error messages to DEBUG_CHANNEL if the outgoing request rate exceeds the server limit. PARCEL_COUNT_TOTAL Used with llGetParcelPrimCount to get the total number of prims on the parcel PARCEL_COUNT_OWNER Used with llGetParcelPrimCount to get the number of prims on the parcel owned by the owner @@ -501,17 +547,17 @@ PARCEL_COUNT_OTHER Used with llGetParcelPrimCount to get the number of prims on PARCEL_COUNT_SELECTED Used with llGetParcelPrimCount to get the number of prims on the parcel currently selected or sat upon PARCEL_COUNT_TEMP Used with llGetParcelPrimCount to get the number of prims on the parcel that are temp on rez -PARCEL_DETAILS_NAME Used with llGetParcelDetails to get the parcel name. -PARCEL_DETAILS_DESC Used with llGetParcelDetails to get the parcel description. -PARCEL_DETAILS_OWNER Used with llGetParcelDetails to get the parcel owner id. -PARCEL_DETAILS_GROUP Used with llGetParcelDetails to get the parcel group id. -PARCEL_DETAILS_AREA Used with llGetParcelDetails to get the parcel area in square meters. -PARCEL_DETAILS_ID Used with llGetParcelDetails to get the parcel id. -PARCEL_DETAILS_SEE_AVATARS Used with llGetParcelDetails to get the avatars visibility setting. +PARCEL_DETAILS_NAME Used with llGetParcelDetails to get the parcel name +PARCEL_DETAILS_DESC Used with llGetParcelDetails to get the parcel description +PARCEL_DETAILS_OWNER Used with llGetParcelDetails to get the parcel owner id +PARCEL_DETAILS_GROUP Used with llGetParcelDetails to get the parcel group id +PARCEL_DETAILS_AREA Used with llGetParcelDetails to get the parcel area in square meters +PARCEL_DETAILS_ID Used with llGetParcelDetails to get the parcel id +PARCEL_DETAILS_SEE_AVATARS Used with llGetParcelDetails to get the avatars visibility setting -STRING_TRIM_HEAD Used with llStringTrim to trim leading spaces from a string. -STRING_TRIM_TAIL Used with llStringTrim to trim trailing spaces from a string. -STRING_TRIM Used with llStringTrim to trim both leading and trailing spaces from a string. +STRING_TRIM_HEAD Used with llStringTrim to trim leading spaces from a string +STRING_TRIM_TAIL Used with llStringTrim to trim trailing spaces from a string +STRING_TRIM Used with llStringTrim to trim both leading and trailing spaces from a string CLICK_ACTION_NONE Used with llSetClickAction to disable the click action CLICK_ACTION_TOUCH Used with llSetClickAction to set touch as the default action when object is clicked @@ -523,9 +569,9 @@ CLICK_ACTION_PLAY Used with llSetClickAction to set play as the default ac CLICK_ACTION_OPEN_MEDIA Used with llSetClickAction to set open-media as the default action when object is clicked CLICK_ACTION_ZOOM Used with llSetClickAction to set zoom in as the default action when object is clicked -TOUCH_INVALID_TEXCOORD Value returned by llDetectedTouchUV() and llDetectedTouchST() when the touch position is not valid. -TOUCH_INVALID_VECTOR Value returned by llDetectedTouchPos(), llDetectedTouchNormal(), and llDetectedTouchBinormal() when the touch position is not valid. -TOUCH_INVALID_FACE Value returned by llDetectedTouchFace() when the touch position is not valid. +TOUCH_INVALID_TEXCOORD Value returned by llDetectedTouchUV() and llDetectedTouchST() when the touch position is not valid +TOUCH_INVALID_VECTOR Value returned by llDetectedTouchPos(), llDetectedTouchNormal(), and llDetectedTouchBinormal() when the touch position is not valid +TOUCH_INVALID_FACE Value returned by llDetectedTouchFace() when the touch position is not valid PRIM_MEDIA_ALT_IMAGE_ENABLE Used with ll{Get,Set}PrimMediaParams to enable the default alt image for media PRIM_MEDIA_CONTROLS Used with ll{Get,Set}PrimMediaParams to determine the controls shown for media @@ -567,6 +613,7 @@ STATUS_NOT_SUPPORTED Feature not supported STATUS_INTERNAL_ERROR An internal error occurred STATUS_WHITELIST_FAILED URL failed to pass whitelist +# windlight constants WL_WATER_COLOR Windlight Water Colour WL_WATER_FOG_DENSITY_EXPONENT Windlight Water Fog Density Exponent WL_UNDERWATER_FOG_MODIFIER Windlight Underwater Fog Modifier @@ -605,6 +652,112 @@ WL_CLOUD_SCROLL_Y_LOCK Windlight Cloud Scroll Y Lock WL_CLOUD_SCROLL_X_LOCK Windlight Cloud Scroll X Lock WL_DRAW_CLASSIC_CLOUDS Windlight Draw Classic Clouds +# keyframe constants +KFM_COMMAND Option for llSetKeyframedMotion(), followed by one of KFM_CMD_STOP, KFM_CMD_PLAY, KFM_CMD_PAUSE. Note that KFM_COMMAND must be the only option in the list, and cannot be specified in the same function call that sets the keyframes list. +KFM_MODE Option for llSetKeyframedMotion(), used to specify the playback mode, followed by one of KFM_FORWARD, KFM_LOOP, KFM_PING_PONG or KFM_REVERSE. +KFM_DATA Option for llSetKeyframedMotion(), followed by a bitwise combination of KFM_TRANSLATION and KFM_ROTATION. If you specify one or the other, you should only include translations or rotations in your keyframe list. +KFM_FORWARD Option for llSetKeyframedMotion(), used after KFM_MODE to specify the forward playback mode. +KFM_LOOP Option for llSetKeyframedMotion(), used after KFM_MODE to specify the loop playback mode. +KFM_PING_PONG Option for llSetKeyframedMotion(), used after KFM_MODE to specify the ping pong playback mode. +KFM_REVERSE Option for llSetKeyframedMotion(), used after KFM_MODE to specify the reverse playback mode. +KFM_ROTATION Option for llSetKeyframedMotion(), used after KFM_DATA, possibly as a bitwise combination with KFM_TRANSLATION. +KFM_TRANSLATION Option for llSetKeyframedMotion(), used after KFM_DATA, possibly as a bitwise combination with KFM_ROTATION. +KFM_CMD_PLAY Option for llSetKeyframedMotion(), used after KFM_COMMAND to play the motion. +KFM_CMD_STOP Option for llSetKeyframedMotion(), used after KFM_COMMAND to stop the motion. +KFM_CMD_PAUSE Option for llSetKeyframedMotion(), used after KFM_COMMAND to pause the motion. + +# OSSL constants +STATS_TIME_DILATION +STATS_SIM_FPS +STATS_PHYSICS_FPS +STATS_AGENT_UPDATES +STATS_ROOT_AGENTS +STATS_CHILD_AGENTS +STATS_TOTAL_PRIMS +STATS_ACTIVE_PRIMS +STATS_FRAME_MS +STATS_NET_MS +STATS_PHYSICS_MS +STATS_IMAGE_MS +STATS_OTHER_MS +STATS_IN_PACKETS_PER_SECOND +STATS_OUT_PACKETS_PER_SECOND +STATS_UNACKED_BYTES +STATS_AGENT_MS +STATS_PENDING_DOWNLOADS +STATS_PENDING_UPLOADS +STATS_ACTIVE_SCRIPTS +STATS_SCRIPT_LPS + +## Constants for osNpc* functions +NPC +OS_NPC_CREATOR_OWNED +OS_NPC_NOT_OWNED +OS_NPC_SENSE_AS_AGENT +OS_NPC_FLY +OS_NPC_NO_FLY +OS_NPC_LAND_AT_TARGET +OS_NPC_SIT_NOW + +## Missing LSL constants (from http://wiki.secondlife.com/wiki/Category:LSL_Constants) + +# physics constants +DENSITY For use with llSetPhysicsMaterial() as a bitwise value in its material_bits parameter, to set the density. +FRICTION For use with llSetPhysicsMaterial() as a bitwise value in its material_bits parameter, to set the friction. +RESTITUTION For use with llSetPhysicsMaterial() as a bitwise value in its material_bits parameter, to set the restitution. +GRAVITY_MULTIPLIER For use with llSetPhysicsMaterial() as a bitwise value in its material_bits parameter, to set the gravity multiplier. + +##Even more missing constants, thanks to Justin Clark Casey for pointing me into the right direction +##Liru: Were these supposed to be LSL? They're undocumented, commenting out for now. +#CAMERA_FOCUS_OFFSET_X +#CAMERA_FOCUS_OFFSET_Y +#CAMERA_FOCUS_OFFSET_Z +#CAMERA_FOCUS_X +#CAMERA_FOCUS_Y +#CAMERA_FOCUS_Z +#CAMERA_POSITION_X +#CAMERA_POSITION_Y +#CAMERA_POSITION_Z +#CHANGED_ANIMATION +#CHANGED_REGION_RESTART +#DATA_SIM_RELEASE +#LIST_STAT_HARMONIC_MEAN +#PARCEL_DETAILS_CLAIMDATE +#VEHICLE_FLAG_LOCK_HOVER_HEIGHT +#VEHICLE_FLAG_LOCK_ROTATION +#VEHICLE_FLAG_NO_X +#VEHICLE_FLAG_NO_Y +#VEHICLE_FLAG_NO_Z +#VEHICLE_RANGE_BLOCK +#VEHICLE_ROLL_FRAME +#LSL_STATUS_BOUNDS_ERROR +#LSL_STATUS_INTERNAL_ERROR +#LSL_STATUS_MALFORMED_PARAMS +#LSL_STATUS_NOT_FOUND +#LSL_STATUS_NOT_SUPPORTED +#LSL_STATUS_OK +#LSL_STATUS_TYPE_MISMATCH +#LSL_STATUS_WHITELIST_FAILED + +# castray constants +RCERR_UNKNOWN Returned by llCastRay() when the raycast failed for an unspecified reason. +RCERR_SIM_PERF_LOW Returned by llCastRay() when the raycast failed because simulator performance is low. +RCERR_CAST_TIME_EXCEEDED Returned by llCastRay() when the raycast failed because the parcel or agent has exceeded the maximum time allowed for raycasting. + +RC_REJECT_TYPES Option for llCastRay() used to ignore specific types of objects, followed with a bitwise combination of RC_REJECT_AGENTS, RC_REJECT_PHYSICAL, RC_REJECT_NONPHYSICAL and RC_REJECT_LAND. +RC_DETECT_PHANTOM Option for llCastRay() followed with TRUE to detect phantom AND volume detect objects, FASLE otherwise. +RC_DATA_FLAGS Option for llCastRay() followed with a bitwise combination of RC_GET_NORMAL, RC_GET_ROOT_KEY and RC_GET_LINK_NUM. +RC_MAX_HITS Option for llCastRay() followed with an integer specifying the maximum number of hits to return (must be <= 256). + +RC_REJECT_AGENTS Flag used in the RC_REJECT_TYPES mask to reject agents in llCastRay(). +RC_REJECT_PHYSICAL Flag used in the RC_REJECT_TYPES mask to reject physical objects in llCastRay(). +RC_REJECT_NONPHYSICAL Flag used in the RC_REJECT_TYPES mask to reject non-physical objects in llCastRay(). +RC_REJECT_LAND Flag used in the RC_REJECT_TYPES mask to reject land in llCastRay(). + +RC_GET_NORMAL Flag used in the RC_DATA_FLAGS mask to get hit normals in llCastRay() results. +RC_GET_ROOT_KEY Flag used in the RC_DATA_FLAGS mask to get root keys in llCastRay() results. +RC_GET_LINK_NUM Flag used in the RC_DATA_FLAGS mask to get link numbers in llCastRay() results. + # string constants [word .1, .3, .5] NULL_KEY Indicates an empty key @@ -650,12 +803,11 @@ return Leave current function or event handler # Comment [one_sided_delimiter .8, .3, .15] // Comment:Non-functional commentary or disabled code -# for now two_sided_delimiter spans from the token to the token, reversed. (eg: /* to */) -[two_sided_delimiter .8, .3, .15] -/* Comment:Non-functional commentary or disabled code +[two_sided_delimiter_esc .8, .3, .15] +/* */ Comment:Non-functional commentary or disabled code # String literals [two_sided_delimiter_esc 0, .2, 0] -" String literal +" " String literal -#functions are supplied by the program now. +#functions are supplied by the program now diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 850540ef1..5dc30d0c3 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -21,6 +21,19 @@ 1 + SianaVoidWaterSubdivision + + Comment + Number of tiles of void water + Persist + 1 + Type + U32 + Value + 8 + + + SGAbsolutePointer Comment @@ -278,29 +291,6 @@ - SianaJ2CSizeExponent - - Comment - Exponent of size estimator. Should be between 0.0 and 1.0 - Persist - 1 - Type - F32 - Value - 1.0 - - SianaJ2CSizeOffset - - Comment - Number of bytes to add to size estimator. - Persist - 1 - Type - S32 - Value - 0 - - SianaLegacyJ2CSize Comment @@ -782,7 +772,7 @@ Type Boolean Value - 1 + 0 PrivateLookAt @@ -806,17 +796,6 @@ Value 0 - EmeraldUseProperArc - - Comment - Enables/Disables a fixed ARC counter - Persist - 1 - Type - Boolean - Value - 0 - EmeraldBoobMass Comment @@ -848,17 +827,6 @@ Type Boolean Value - 1 - - EmeraldBreastSportsBra - - Comment - allows disabling the physics for 1 av, in case their outfit looks wrong with it on - Persist - 1 - Type - Boolean - Value 0 EmeraldBoobVelMax @@ -1790,6 +1758,17 @@ Value 0.5 + AudioLevelWind + + Comment + Audio level of wind noise when standing still + Persist + 1 + Type + F32 + Value + 0.075 + AudioStreamingMusic Comment @@ -2076,6 +2055,28 @@ Value 2 + AvatarBakedTextureUploadTimeout + + Comment + Specifes the maximum time in seconds to wait before sending your baked textures for avatar appearance. Set to 0 to disable and wait until all baked textures are at highest resolution. + Persist + 1 + Type + U32 + Value + 60 + + AvatarBakedLocalTextureUpdateTimeout + + Comment + Specifes the maximum time in seconds to wait before updating your appearance during appearance mode. + Persist + 1 + Type + U32 + Value + 10 + AvatarPhysics Comment @@ -2201,38 +2202,16 @@ Value http://www.singularityviewer.org - BrowserCookiesEnabled + BrowserIgnoreSSLCertErrors Comment - Enable Cookes in WebKit + FOR TESTING ONLY: Tell the built-in web browser to ignore SSL cert errors. Persist 1 Type Boolean Value - 1 - - BrowserPluginsEnabled - - Comment - Enable Mozilla Plug-Ins in WebKit - Persist - 1 - Type - Boolean - Value - 1 - - BrowserJavascriptEnabled - - Comment - Enable JavaScript execution in WebKit - Persist - 1 - Type - Boolean - Value - 1 + 0 PluginAttachDebuggerToPlugins @@ -2898,10 +2877,10 @@ 6.0 - CameraOffsetDefault + CameraOffsetRearView Comment - Default camera offset from avatar + Initial camera offset from avatar in Rear View Persist 1 Type @@ -2913,6 +2892,36 @@ 0.75 + CameraOffsetFrontView + + Comment + Initial camera offset from avatar in Front View + Persist + 1 + Type + Vector3 + Value + + 2.2 + 0.0 + 0.0 + + + CameraOffsetGroupView + + Comment + Initial camera offset from avatar in Group View + Persist + 1 + Type + Vector3 + Value + + -1.0 + 0.7 + 0.5 + + CameraOffsetScale Comment @@ -2950,6 +2959,18 @@ Value 1.0 + CameraPreset + + Comment + Preset camera position - view (0 - rear, 1 - front, 2 - group) + Persist + 1 + Type + U32 + Value + 0 + + CameraFocusTransitionTime Comment @@ -3897,6 +3918,28 @@ Value 1 + BrowserJavascriptEnabled + + Comment + Enable Javascript in the built-in Web browser? + Persist + 1 + Type + Boolean + Value + 1 + + BrowserPluginsEnabled + + Comment + Enable Web plugins in the built-in Web browser? + Persist + 1 + Type + Boolean + Value + 1 + CreateToolCopyCenters Comment @@ -3994,8 +4037,30 @@ Type String Value - + + DebugAvatarRezTime + + Comment + Display times for avatars to resolve. + Persist + 1 + Type + Boolean + Value + 0 + + DebugAvatarLocalTexLoadedTime + + Comment + Display time for loading avatar local textures. + Persist + 1 + Type + Boolean + Value + 0 + DebugBeaconLineWidth Comment @@ -5041,6 +5106,28 @@ Value 1 + EnableGestureSounds + + Comment + Play sounds from gestures + Persist + 1 + Type + Boolean + Value + 1 + + EnableGestureSoundsSelf + + Comment + Play sounds from your gestures when EnableGestureSounds is false. (Useless otherewise) + Persist + 1 + Type + Boolean + Value + 1 + EnableMouselook Comment @@ -6624,14 +6711,14 @@ Value 0 - FocusOffsetDefault + FocusOffsetRearView Comment - Default focus point offset relative to avatar (x-axis is forward) + Initial focus point offset relative to avatar for the camera preset Rear View (x-axis is forward) Persist 1 Type - Vector3 + Vector3D Value 1.0 @@ -6639,6 +6726,36 @@ 1.0 + FocusOffsetFrontView + + Comment + Initial focus point offset relative to avatar for the camera preset Front View + Persist + 1 + Type + Vector3D + Value + + 0.0 + 0.0 + 0.0 + + + FocusOffsetGroupView + + Comment + Initial focus point offset relative to avatar for the camera preset Group View + Persist + 1 + Type + Vector3D + Value + + 1.5 + 0.7 + 1.0 + + FocusPosOnLogout Comment @@ -6709,6 +6826,17 @@ Value 0 + ForceAssetFail + + Comment + Force wearable fetches to fail for this asset type. + Persist + 1 + Type + U32 + Value + 255 + ForceShowGrid Comment @@ -7119,6 +7247,72 @@ Value 1.0 + InventoryDisplayInbox + + Comment + Override received items inventory inbox display + Persist + 0 + Type + Boolean + Value + 0 + + InventoryDisplayOutbox + + Comment + Override merchant inventory outbox display + Persist + 0 + Type + Boolean + Value + 0 + + InventoryOutboxLogging + + Comment + Enable debug output associated with the Merchant Outbox. + Persist + 1 + Type + Boolean + Value + 0 + + InventoryOutboxMaxFolderCount + + Comment + Maximum number of subfolders allowed in a listing in the merchant outbox. + Persist + 0 + Type + U32 + Value + 21 + + InventoryOutboxMaxFolderDepth + + Comment + Maximum number of nested levels of subfolders allowed in a listing in the merchant outbox. + Persist + 0 + Type + U32 + Value + 4 + + InventoryOutboxMaxItemCount + + Comment + Maximum number of items allowed in a listing in the merchant outbox. + Persist + 0 + Type + U32 + Value + 200 + InventorySortOrder Comment @@ -7949,6 +8143,17 @@ Value 128.0 + MaxWearableWaitTime + + Comment + Max seconds to wait for wearable assets to fetch. + Persist + 1 + Type + F32 + Value + 60.0 + MeanCollisionBump Comment @@ -8004,6 +8209,17 @@ Value 0 + MediaPluginDebugging + + Comment + Turn on debugging messages that may help diagnosing media issues (WARNING: May reduce performance). + Persist + 1 + Type + Boolean + Value + 0 + MediaControlFadeTime Comment @@ -8037,17 +8253,17 @@ Value 0 - MemoryFailurePreventionEnabled - - Comment - If set, the viewer will quit to avoid crash when memory failure happens - Persist - 1 - Type - Boolean - Value - 0 - + MemoryFailurePreventionEnabled + + Comment + If set, the viewer will quit to avoid crash when memory failure happens + Persist + 1 + Type + Boolean + Value + 0 + MemoryLogFrequency Comment @@ -8068,7 +8284,7 @@ Type Boolean Value - 0 + 0 MemoryPrivatePoolSize @@ -8158,17 +8374,6 @@ Value 0 - MeshUploadTimeOut - - Comment - Maximum time in seconds for llcurl to execute a mesh uploading request - Persist - 1 - Type - S32 - Value - 600 - MeshUploadFakeErrors Comment @@ -8180,8 +8385,18 @@ Value 0 - - MigrateCacheDirectory + MeshUploadTimeOut + + Comment + Maximum time in seconds for llcurl to execute a mesh uploading request + Persist + 1 + Type + S32 + Value + 600 + + MigrateCacheDirectory Comment Check for old version of disk cache to migrate to current location @@ -8312,7 +8527,7 @@ 29 - DisableWindAudio + MuteWind Comment Disable the wind audio effect @@ -8409,20 +8624,20 @@ Type Boolean Value - 1 - - SinguMuteGestures - - Comment - Mute gestures other than your own. - Persist - 1 - Type - Boolean - Value 0 - NearMeRange + MyOutfitsAutofill + + Comment + Always autofill My Outfits from library when empty (else happens just once). + Persist + 1 + Type + Boolean + Value + 0 + + NearMeRange Comment Search radius for nearby avatars @@ -9867,32 +10082,32 @@ RenderShadowNearDist Comment - Near clip plane of shadow camera (affects precision of depth shadows). - Persist - 1 - Type - Vector3 - Value - - 256 - 256 - 256 - - - RenderShadowClipPlanes - - Comment - Near clip plane split distances for shadow map frusta. - Persist - 1 - Type - Vector3 - Value - - 1.0 - 12.0 - 32.0 - + Near clip plane of shadow camera (affects precision of depth shadows). + Persist + 1 + Type + Vector3 + Value + + 256 + 256 + 256 + + + RenderShadowClipPlanes + + Comment + Near clip plane split distances for shadow map frusta. + Persist + 1 + Type + Vector3 + Value + + 1.0 + 12.0 + 32.0 + RenderShadowSplitExponent @@ -9957,55 +10172,55 @@ Value 0.5 - RenderSSAOScale - - Comment - Scaling factor for the area to sample for occluders (pixels at 1 meter away, inversely varying with distance) - Persist - 1 - Type - F32 - Value - 500.0 - - RenderSSAOMaxScale - - Comment - Maximum screen radius for sampling (pixels) - Persist - 1 - Type - U32 - Value - 200 - - RenderSSAOFactor - - Comment - Occlusion sensitivity factor for ambient occlusion (larger is more) - Persist - 1 - Type - F32 - Value - 0.30 - - RenderSSAOEffect - - Comment - Multiplier for (1) value and (2) saturation (HSV definition), for areas which are totally occluded. Blends with original color for partly-occluded areas. (Third component is unused.) - Persist - 1 - Type - Vector3 - Value - - 0.80 - 1.00 - 0.00 - - - RenderBumpmapMinDistanceSquared + RenderSSAOScale + + Comment + Scaling factor for the area to sample for occluders (pixels at 1 meter away, inversely varying with distance) + Persist + 1 + Type + F32 + Value + 500.0 + + RenderSSAOMaxScale + + Comment + Maximum screen radius for sampling (pixels) + Persist + 1 + Type + U32 + Value + 200 + + RenderSSAOFactor + + Comment + Occlusion sensitivity factor for ambient occlusion (larger is more) + Persist + 1 + Type + F32 + Value + 0.30 + + RenderSSAOEffect + + Comment + Multiplier for (1) value and (2) saturation (HSV definition), for areas which are totally occluded. Blends with original color for partly-occluded areas. (Third component is unused.) + Persist + 1 + Type + Vector3 + Value + + 0.80 + 1.00 + 0.00 + + + RenderBumpmapMinDistanceSquared Comment Maximum distance at which to render bumpmapped primitives (distance in meters, squared) @@ -10016,17 +10231,17 @@ Value 100.0 - RenderNormalMapScale - - Comment - Scaler applied to height map when generating normal maps - Persist - 1 - Type - F32 - Value - 64 - + RenderNormalMapScale + + Comment + Scaler applied to height map when generating normal maps + Persist + 1 + Type + F32 + Value + 64 + RenderCubeMap Comment @@ -10104,29 +10319,29 @@ Value 0 - RenderDelayCreation - - Comment - Throttle creation of drawables. - Persist - 1 - Type - Boolean - Value - 0 - + RenderDelayCreation + + Comment + Throttle creation of drawables. + Persist + 1 + Type + Boolean + Value + 0 + - RenderAnimateRes - - Comment - Animate rezing prims. - Persist - 1 - Type - Boolean - Value - 0 - + RenderAnimateRes + + Comment + Animate rezing prims. + Persist + 1 + Type + Boolean + Value + 0 + RenderBakeSunlight @@ -10139,7 +10354,7 @@ Value 0 - + \n", wearable_name.c_str() ); - for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) + for (LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam()) { LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; if( (viewer_param->getWearableType() == type) && (viewer_param->isTweakable() ) ) { - apr_file_printf( file, "\t\t\n", - viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getWeight() ); + apr_file_printf(file, "\t\t\n", + viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getWeight()); } } - for(U8 te = 0; te < TEX_NUM_INDICES; te++) + for (U8 te = 0; te < TEX_NUM_INDICES; te++) { - if( LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te) == type ) + if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te) == type) { - LLViewerTexture* te_image = avatar->getTEImage((ETextureIndex)te); + // MULTIPLE_WEARABLES: extend to multiple wearables? + LLViewerTexture* te_image = ((LLVOAvatar *)(gAgentAvatarp))->getImage((ETextureIndex)te, 0); if( te_image ) { std::string uuid_str; @@ -9584,8 +8724,14 @@ void LLVOAvatar::dumpArchetypeXML( void* ) } apr_file_printf( file, "\t\n" ); apr_file_printf( file, "\n\n" ); + //explictly close the file if it is still open which it should be + if (file) + { + outfile.close(); + } } + void LLVOAvatar::setVisibilityRank(U32 rank) { if (mDrawable.isNull() || mDrawable->isDead()) @@ -9665,7 +8811,7 @@ void LLVOAvatar::cullAvatarsByPixelArea() } S32 grey_avatars = 0; - if ( LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars) ) + if (LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars)) { LLVOAvatar::deleteCachedImages(false); } @@ -9687,149 +8833,10 @@ void LLVOAvatar::cullAvatarsByPixelArea() } } -const LLUUID& LLVOAvatar::grabLocalTexture(ETextureIndex index) -{ - if (canGrabLocalTexture(index)) - { - return getTEImage( index )->getID(); - } - return LLUUID::null; -} - -BOOL LLVOAvatar::canGrabLocalTexture(ETextureIndex index) -{ - // Check if the texture hasn't been baked yet. - if (!isTextureDefined(index)) - { - lldebugs << "getTEImage( " << (U32) index << " )->getID() == IMG_DEFAULT_AVATAR" << llendl; - return FALSE; - } - - if (gAgent.isGodlike() && !gAgent.getAdminOverride()) - return TRUE; - - // Check permissions of textures that show up in the - // baked texture. We don't want people copying people's - // work via baked textures. - /* switch(index) - case TEX_EYES_BAKED: - textures.push_back(TEX_EYES_IRIS); */ - const LLVOAvatarDictionary::TextureEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); - if (!text_dict->mIsUsedByBakedTexture) return FALSE; - - const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index); - for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin(); - iter != baked_dict->mLocalTextures.end(); - iter++) - { - const ETextureIndex t_index = (*iter); - lldebugs << "Checking index " << (U32) t_index << llendl; - const LLUUID& texture_id = getTEImage( t_index )->getID(); - if (texture_id != IMG_DEFAULT_AVATAR) - { - // Search inventory for this texture. - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - LLAssetIDMatches asset_id_matches(texture_id); - gInventory.collectDescendentsIf(LLUUID::null, - cats, - items, - LLInventoryModel::INCLUDE_TRASH, - asset_id_matches); - - BOOL can_grab = FALSE; - lldebugs << "item count for asset " << texture_id << ": " << items.count() << llendl; - if (items.count()) - { - // search for full permissions version - for (S32 i = 0; i < items.count(); i++) - { - LLInventoryItem* itemp = items[i]; - LLPermissions item_permissions = itemp->getPermissions(); - if ( item_permissions.allowOperationBy( - PERM_MODIFY, gAgent.getID(), gAgent.getGroupID()) && - item_permissions.allowOperationBy( - PERM_COPY, gAgent.getID(), gAgent.getGroupID()) && - item_permissions.allowOperationBy( - PERM_TRANSFER, gAgent.getID(), gAgent.getGroupID()) ) - { - can_grab = TRUE; - break; - } - } - } - if (!can_grab) return FALSE; - } - } - - return TRUE; -} - -void LLVOAvatar::dumpLocalTextures() -{ - llinfos << "Local Textures:" << llendl; - - /* ETextureIndex baked_equiv[] = { - TEX_UPPER_BAKED, - if (isTextureDefined(baked_equiv[i])) */ - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - iter++) - { - const LLVOAvatarDictionary::TextureEntry *text_dict = iter->second; - if (!text_dict->mIsLocalTexture || !text_dict->mIsUsedByBakedTexture) - continue; - - const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; - const ETextureIndex baked_equiv = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex; - - const std::string &name = text_dict->mName; - const LocalTextureData &local_tex_data = mLocalTextureData[iter->first]; - if (isTextureDefined(baked_equiv)) - { -#if LL_RELEASE_FOR_DOWNLOAD - // End users don't get to trivially see avatar texture IDs, makes textures - // easier to steal. JC - llinfos << "LocTex " << name << ": Baked " << llendl; -#else - llinfos << "LocTex " << name << ": Baked " << getTEImage( baked_equiv )->getID() << llendl; -#endif - } - else if (local_tex_data.mImage.notNull()) - { - if( local_tex_data.mImage->getID() == IMG_DEFAULT_AVATAR ) - { - llinfos << "LocTex " << name << ": None" << llendl; - } - else - { - const LLViewerFetchedTexture* image = local_tex_data.mImage; - - llinfos << "LocTex " << name << ": " - << "Discard " << image->getDiscardLevel() << ", " - << "(" << image->getWidth() << ", " << image->getHeight() << ") " -#if !LL_RELEASE_FOR_DOWNLOAD - // End users don't get to trivially see avatar texture IDs, - // makes textures easier to steal - << image->getID() << " " -#endif - << "Priority: " << image->getDecodePriority() - << llendl; - } - } - else - { - llinfos << "LocTex " << name << ": No LLViewerTexture" << llendl; - } - } -} - -void LLVOAvatar::startAppearanceAnimation(BOOL set_by_user, BOOL play_sound) +void LLVOAvatar::startAppearanceAnimation() { if(!mAppearanceAnimating) { - mAppearanceAnimSetByUser = set_by_user; mAppearanceAnimating = TRUE; mAppearanceMorphTimer.reset(); mLastAppearanceBlendTime = 0.f; @@ -9853,13 +8860,14 @@ LLVOAvatar::LLVOAvatarXmlInfo::LLVOAvatarXmlInfo() LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo() { std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer()); - std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); + std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer()); deleteAndClear(mTexSkinColorInfo); deleteAndClear(mTexHairColorInfo); deleteAndClear(mTexEyeColorInfo); - std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); + std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer()); + std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer()); } //----------------------------------------------------------------------------- @@ -10281,13 +9289,56 @@ BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) return TRUE; } -// warning: order(N) not order(1) -S32 LLVOAvatar::getAttachmentCount() +//----------------------------------------------------------------------------- +// parseXmlDriverNodes(): parses nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root) { - S32 count = mAttachmentPoints.size(); - return count; -} + LLXmlTreeNode* masks = root->getChildByName( "morph_masks" ); + if( !masks ) + { + return FALSE; + } + for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" ); + grand_child; + grand_child = masks->getNextNamedChild()) + { + LLVOAvatarMorphInfo* info = new LLVOAvatarMorphInfo(); + + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("morph_name"); + if (!grand_child->getFastAttributeString(name_string, info->mName)) + { + llwarns << "No name supplied for morph mask." << llendl; + delete info; + continue; + } + + static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region"); + if (!grand_child->getFastAttributeString(region_string, info->mRegion)) + { + llwarns << "No region supplied for morph mask." << llendl; + delete info; + continue; + } + + static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer"); + if (!grand_child->getFastAttributeString(layer_string, info->mLayer)) + { + llwarns << "No layer supplied for morph mask." << llendl; + delete info; + continue; + } + + // optional parameter. don't throw a warning if not present. + static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); + grand_child->getFastAttributeBOOL(invert_string, info->mInvert); + + mMorphMaskInfoList.push_back(info); + } + + return TRUE; +} //virtual void LLVOAvatar::updateRegion(LLViewerRegion *regionp) @@ -10309,21 +9360,6 @@ std::string LLVOAvatar::getFullname() const return name; } -LLTexLayerSet* LLVOAvatar::getLayerSet(ETextureIndex index) const -{ - /* switch(index) - case TEX_HEAD_BAKED: - case TEX_HEAD_BODYPAINT: - return mHeadLayerSet; */ - const LLVOAvatarDictionary::TextureEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); - if (text_dict->mIsUsedByBakedTexture) - { - const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; - return mBakedTextureDatas[baked_index].mTexLayerSet; - } - return NULL; -} - LLHost LLVOAvatar::getObjectHost() const { LLViewerRegion* region = getRegion(); @@ -10364,7 +9400,7 @@ BOOL LLVOAvatar::updateLOD() BOOL res = updateJointLODs(); LLFace* facep = mDrawable->getFace(0); - if (!facep->getVertexBuffer()) + if (!facep || !facep->getVertexBuffer()) { dirtyMesh(2); } @@ -10563,7 +9599,7 @@ void LLVOAvatar::idleUpdateRenderCost() { const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; // TODO: MULTI-WEARABLE: handle multiple textures for self - const LLViewerTexture* te_image = getTEImage(iter->first);//getImage(iter->first,0); + const LLViewerTexture* te_image = getImage(iter->first,0); if (!te_image) continue; LLUUID image_id = te_image->getID(); @@ -10577,7 +9613,9 @@ void LLVOAvatar::idleUpdateRenderCost() } } - setDebugText(llformat("%d", cost)); + + std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); + setDebugText(llformat("%s %d", viz_string.c_str(), cost)); mVisualComplexity = cost; F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f); F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f); @@ -10622,6 +9660,57 @@ const std::string LLVOAvatar::getBakedStatusForPrintout() const } + +//virtual +S32 LLVOAvatar::getTexImageSize() const +{ + return TEX_IMAGE_SIZE_OTHER; +} + +//----------------------------------------------------------------------------- +// Utility functions +//----------------------------------------------------------------------------- + +F32 calc_bouncy_animation(F32 x) +{ + return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f; +} + +//virtual +BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 index ) const +{ + if (isIndexLocalTexture(te)) + { + return FALSE; + } + + return (getImage(te, index)->getID() != IMG_DEFAULT_AVATAR && + getImage(te, index)->getID() != IMG_DEFAULT); +} + +//virtual +BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index) const +{ + if (isIndexLocalTexture(type)) + { + return isTextureDefined(type, index); + } + else + { + // baked textures can use TE images directly + return ((isTextureDefined(type) || isSelf()) + && (getTEImage(type)->getID() != IMG_INVISIBLE + || LLDrawPoolAlpha::sShowDebugAlpha)); + } +} + +//virtual +BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const +{ + // non-self avatars don't have wearables + return FALSE; +} + U32 calc_shame(LLVOVolume* volume, std::set &textures) { if (!volume) @@ -10725,12 +9814,3 @@ U32 calc_shame(LLVOVolume* volume, std::set &textures) return shame; } - -//----------------------------------------------------------------------------- -// Utility functions -//----------------------------------------------------------------------------- - -F32 calc_bouncy_animation(F32 x) -{ - return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f; -} diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index b1c777b49..e0d4b3bf5 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -39,20 +39,25 @@ #include #include +#include + #include "imageids.h" // IMG_INVISIBLE #include "llchat.h" #include "lldrawpoolalpha.h" #include "llviewerobject.h" #include "llcharacter.h" +#include "llcontrol.h" #include "llviewerjointmesh.h" #include "llviewerjointattachment.h" #include "llrendertarget.h" -#include "llwearable.h" #include "llvoavatardefines.h" +#include "lltexglobalcolor.h" +#include "lldriverparam.h" +#include "material_codes.h" // LL_MCODE_END + #include "emeraldboobutils.h" #include "llavatarname.h" - extern const LLUUID ANIM_AGENT_BODY_NOISE; extern const LLUUID ANIM_AGENT_BREATHE_ROT; extern const LLUUID ANIM_AGENT_PHYSICS_MOTION; @@ -70,19 +75,56 @@ class LLVoiceVisualizer; class LLHUDNameTag; class LLHUDEffectSpiral; class LLTexGlobalColor; -class LLTexGlobalColorInfo; -class LLTexLayerSetInfo; -class LLDriverParamInfo; class LLVOAvatarBoneInfo; class LLVOAvatarSkeletonInfo; +class SHClientTagMgr : public LLSingleton, public boost::signals2::trackable +{ +public: + SHClientTagMgr(); + //Fetch updated client_tags_sg1.xml from server + bool fetchDefinitions() const; + //Parse definitions from client_tags_sg1.xml + bool parseDefinitions(); +private: + //Just refreshes the tag for the agent avatar. + //Used for boost::bind to verify agent avatar is valid before calling updateAvatarTag + void updateAgentAvatarTag(); + //Actually generate the tag information for the avatar + const LLSD generateClientTag(const LLVOAvatar* pAvatar) const; +public: + //Generates tag for particular avatar and sets dirty if the tag has changed. Call on received TE updates. + void updateAvatarTag(LLVOAvatar* pAvatar); + //Removes entry in mAvatarTags map. Call on destruction of avatar. + void clearAvatarTag(const LLVOAvatar* pAvatar); + + // Accessors + + //Returns true if tag system is enabled. + bool getIsEnabled() const; + //If a tag entry exists, returns the clientname if found. If is_friend is set, will return "Friend" if AscentShowFriendsTag is true. + const std::string getClientName(const LLVOAvatar* pAvatar, bool is_friend) const; + //Returns ID of tag entry if it exists, else returns a null LLUUID. + const LLUUID getClientID(const LLVOAvatar* pAvatar) const; + //Sets color to either 'status' color, or falls back to client color if status isn't relevant. + //If neither status or client color are found, returns false. + bool getClientColor(const LLVOAvatar* pAvatar, bool check_status, LLColor4& color) const; + +private: + //UUID map associating texture uuids to client info entries parsed from client_tags_sg1.xml + std::map mClientDefinitions; + //UUID map associating avatar uuids to their CURRENT client tag info. + std::map mAvatarTags; +}; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatar // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLVOAvatar : public LLViewerObject, - public LLCharacter + public LLCharacter, + public boost::signals2::trackable { LOG_CLASS(LLVOAvatar); @@ -90,6 +132,7 @@ public: friend class LLVOAvatarSelf; protected: struct LLVOAvatarXmlInfo; + struct LLMaskedMorph; /******************************************************************************** ** ** @@ -106,6 +149,7 @@ protected: virtual ~LLVOAvatar(); BOOL loadSkeletonNode(); BOOL loadMeshNodes(); + virtual BOOL loadLayersets(); /** Initialization ** ** @@ -179,6 +223,7 @@ public: virtual void requestStopMotion(LLMotion* motion); LLMotion* findMotion(const LLUUID& id) const; void startDefaultMotions(); + void dumpAnimationState(); virtual LLJoint* getJoint(const std::string &name); virtual LLJoint* getRootJoint() { return &mRoot; } @@ -233,18 +278,20 @@ public: void idleUpdateLoadingEffect(); void idleUpdateWindEffect(); void idleUpdateNameTag(const LLVector3& root_pos_last); + void idleUpdateNameTagText(BOOL new_name); + LLVector3 idleUpdateNameTagPosition(const LLVector3& root_pos_last); + void idleUpdateNameTagAlpha(BOOL new_name, F32 alpha); + LLColor4 getNameTagColor(bool is_friend); void clearNameTag(); static void invalidateNameTag(const LLUUID& agent_id); // force all name tags to rebuild, useful when display names turned on/off static void invalidateNameTags(); + void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font); void idleUpdateRenderCost(); void idleUpdateBelowWater(); void idleUpdateBoobEffect(); //Emerald - void updateAttachmentVisibility(U32 camera_mode); //Agent only - LLFrameTimer mIdleTimer; - std::string getIdleTime(); //-------------------------------------------------------------------- // Static preferences (controlled by user settings/menus) @@ -278,13 +325,22 @@ public: //-------------------------------------------------------------------- public: BOOL isFullyLoaded() const; - //BOOL isReallyFullyLoaded(); - BOOL updateIsFullyLoaded(); + bool visualParamWeightsAreDefault(); + virtual BOOL getIsCloud() const; + BOOL isFullyTextured() const; + BOOL hasGray() const; + S32 getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = fully textured. + void updateRezzedStatusTimers(); + + S32 mLastRezzedStatus; protected: - bool sendAvatarTexturesRequest(); + BOOL updateIsFullyLoaded(); + BOOL processFullyLoadedChange(bool loading); + void updateRuthTimer(bool loading); F32 calcMorphAmount(); private: + BOOL mFirstFullyVisible; BOOL mFullyLoaded; BOOL mPreviousFullyLoaded; BOOL mFullyLoadedInitialized; @@ -292,6 +348,8 @@ private: S32 mVisualComplexity; LLFrameTimer mFullyLoadedTimer; LLFrameTimer mRuthTimer; +protected: + LLFrameTimer mInvisibleTimer; /** State ** ** @@ -379,8 +437,6 @@ private: **/ public: - // Graphical stuff for objects - maybe broken out into render class later? - U32 renderFootShadows(); U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); bool isVisuallyMuted() const; @@ -407,6 +463,14 @@ private: S32 mUpdatePeriod; S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer. + //-------------------------------------------------------------------- + // Morph masks + //-------------------------------------------------------------------- +public: + BOOL morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); + void addMaskedMorph(LLVOAvatarDefines::EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer); + void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); + //-------------------------------------------------------------------- // Visibility //-------------------------------------------------------------------- @@ -450,6 +514,8 @@ private: F32 mImpostorDistance; F32 mImpostorPixelArea; LLVector3 mLastAnimExtents[2]; + + LLCachedControl mRenderUnloadedAvatar; //-------------------------------------------------------------------- // Wind rippling in clothes @@ -482,6 +548,15 @@ public: private: static S32 sFreezeCounter; + //-------------------------------------------------------------------- + // Constants + //-------------------------------------------------------------------- +public: + virtual LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLViewerTexture::BOOST_AVATAR; } + virtual LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_BAKED; } + virtual S32 getTexImageSize() const; + virtual S32 getTexImageArea() const { return getTexImageSize()*getTexImageSize(); } + /** Rendering ** ** *******************************************************************************/ @@ -495,12 +570,14 @@ private: // Loading status //-------------------------------------------------------------------- public: - BOOL isTextureDefined(U8 te) const; - BOOL isTextureVisible(U8 te) const; + virtual BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; + virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; + virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const; -protected: BOOL isFullyBaked(); static BOOL areAllNearbyInstancesBaked(S32& grey_avatars); + static void getNearbyRezzedStats(std::vector& counts); + static std::string rezStatusToString(S32 status); //-------------------------------------------------------------------- // Baked textures @@ -514,6 +591,7 @@ protected: virtual void removeMissingBakedTextures(); void useBakedTexture(const LLUUID& id); + typedef std::deque morph_list_t; struct BakedTextureData { LLUUID mLastTextureIndex; @@ -524,15 +602,32 @@ protected: U32 mMaskTexName; // Stores pointers to the joint meshes that this baked texture deals with std::vector< LLViewerJointMesh * > mMeshes; // std::vector mJoints[i]->mMeshParts + morph_list_t mMaskedMorphs; }; typedef std::vector bakedtexturedata_vec_t; bakedtexturedata_vec_t mBakedTextureDatas; + LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList ; + BOOL mLoadedCallbacksPaused; //-------------------------------------------------------------------- // Local Textures //-------------------------------------------------------------------- protected: - void setLocalTexture(LLVOAvatarDefines::ETextureIndex i, LLViewerFetchedTexture* tex, BOOL baked_version_exits); - void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked); + virtual void setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index = 0); + virtual void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex type, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index = 0); + // MULTI-WEARABLE: make self-only? + virtual void setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index = 0); + + //-------------------------------------------------------------------- + // Texture accessors + //-------------------------------------------------------------------- +private: + virtual void setImage(const U8 te, LLViewerTexture *imagep, const U32 index); + virtual LLViewerTexture* getImage(const U8 te, const U32 index) const; + + virtual const LLTextureEntry* getTexEntry(const U8 te_num) const; + virtual void setTexEntry(const U8 index, const LLTextureEntry &te); + + void checkTextureLoading() ; //-------------------------------------------------------------------- // Layers //-------------------------------------------------------------------- @@ -546,6 +641,9 @@ protected: public: virtual void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result); virtual void invalidateAll(); + virtual void setCompositeUpdatesEnabled(bool b) {} + virtual void setCompositeUpdatesEnabled(U32 index, bool b) {} + virtual bool isCompositeUpdateEnabled(U32 index) { return false; } //-------------------------------------------------------------------- // Static texture/mesh/baked dictionary @@ -567,74 +665,7 @@ public: private: BOOL mFirstTEMessageReceived; BOOL mFirstAppearanceMessageReceived; - - -//Most this stuff is Agent only - - //-------------------------------------------------------------------- - // Textures and Layers - //-------------------------------------------------------------------- -protected: - void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i); - - - LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const; - S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex index); - - //-------------------------------------------------------------------- - // Other public functions - //-------------------------------------------------------------------- -public: - static void dumpTotalLocalTextureByteCount(); -protected: - void getLocalTextureByteCount( S32* gl_byte_count ); - -public: - void dumpLocalTextures(); - const LLUUID& grabLocalTexture(LLVOAvatarDefines::ETextureIndex index); - BOOL canGrabLocalTexture(LLVOAvatarDefines::ETextureIndex index); - - void setCompositeUpdatesEnabled(BOOL b); - - void setNameFromChat(const std::string &text); - void clearNameFromChat(); - -public: - - //-------------------------------------------------------------------- - // texture compositing (used only by the LLTexLayer series of classes) - //-------------------------------------------------------------------- -public: - BOOL isLocalTextureDataAvailable( const LLTexLayerSet* layerset ); - BOOL isLocalTextureDataFinal( const LLTexLayerSet* layerset ); - LLVOAvatarDefines::ETextureIndex getBakedTE( LLTexLayerSet* layerset ); - void updateComposites(); - //BOOL getLocalTextureRaw( LLVOAvatarDefines::ETextureIndex index, LLImageRaw* image_raw_pp ); - BOOL getLocalTextureGL( LLVOAvatarDefines::ETextureIndex index, LLViewerTexture** image_gl_pp ); - const LLUUID& getLocalTextureID( LLVOAvatarDefines::ETextureIndex index ); - LLGLuint getScratchTexName( LLGLenum format, U32* texture_bytes ); - BOOL bindScratchTexture( LLGLenum format ); - void forceBakeAllTextures(bool slam_for_debug = false); - static void processRebakeAvatarTextures(LLMessageSystem* msg, void**); - void setNewBakedTexture( LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid ); - void setCachedBakedTexture( LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid ); - void requestLayerSetUploads(); - void requestLayerSetUpload(LLVOAvatarDefines::EBakedTextureIndex i); - bool hasPendingBakedUploads(); - static void onLocalTextureLoaded( BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); - static void onChangeSelfInvisible(BOOL newvalue); - void setInvisible(BOOL newvalue); - - void wearableUpdated(LLWearableType::EType type, BOOL upload_result = TRUE); - - //-------------------------------------------------------------------- - // texture compositing - //-------------------------------------------------------------------- -public: - void setLocTexTE( U8 te, LLViewerTexture* image, BOOL set_by_user ); - void setupComposites(); - /** Textures ** ** *******************************************************************************/ @@ -680,7 +711,7 @@ protected: public: void processAvatarAppearance(LLMessageSystem* mesgsys); void hideSkirt(); - void startAppearanceAnimation(BOOL set_by_user, BOOL play_sound); + void startAppearanceAnimation(); LLPolyMesh* getMesh(LLPolyMeshSharedData* shared_data); //-------------------------------------------------------------------- @@ -692,7 +723,6 @@ private: BOOL mAppearanceAnimating; LLFrameTimer mAppearanceMorphTimer; F32 mLastAppearanceBlendTime; - BOOL mAppearanceAnimSetByUser; //1.23 public: typedef std::map lod_mesh_map_t; @@ -704,16 +734,16 @@ public: // Clothing colors (convenience functions to access visual parameters) //-------------------------------------------------------------------- public: - void setClothesColor( LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL set_by_user ); + void setClothesColor(LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake); LLColor4 getClothesColor(LLVOAvatarDefines::ETextureIndex te); - static BOOL teToColorParams( LLVOAvatarDefines::ETextureIndex te, const char* param_name[3] ); + static BOOL teToColorParams(LLVOAvatarDefines::ETextureIndex te, U32 *param_name); //-------------------------------------------------------------------- // Global colors //-------------------------------------------------------------------- public: LLColor4 getGlobalColor(const std::string& color_name ) const; - void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL set_by_user ); + void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake); private: LLTexGlobalColor* mTexSkinColor; LLTexGlobalColor* mTexHairColor; @@ -728,13 +758,6 @@ public: U32 getVisibilityRank() const { return mVisibilityRank; } // unused static S32 sNumVisibleAvatars; // Number of instances of this class static LLColor4 getDummyColor(); - - //-------------------------------------------------------------------- - // Customize - //-------------------------------------------------------------------- -public: - static void onCustomizeStart(); - static void onCustomizeEnd(); /** Appearance ** ** *******************************************************************************/ @@ -745,21 +768,19 @@ public: **/ public: - BOOL isWearingWearableType( LLWearableType::EType type ) const; + virtual BOOL isWearingWearableType(LLWearableType::EType type ) const; //-------------------------------------------------------------------- // Attachments //-------------------------------------------------------------------- public: void clampAttachmentPositions(); - BOOL attachObject(LLViewerObject *viewer_object); - BOOL detachObject(LLViewerObject *viewer_object); + virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object); + virtual BOOL detachObject(LLViewerObject *viewer_object); void cleanupAttachedMesh( LLViewerObject* pVO ); - static LLVOAvatar* findAvatarFromAttachment( LLViewerObject* obj ); + static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj); protected: -// [RLVa:KB] - Checked: 2009-12-18 (RLVa-1.1.0i) | Added: RLVa-1.1.0i - LLViewerJointAttachment* getTargetAttachmentPoint(const LLViewerObject* viewer_object) const; -// [/RLVa:KB] + LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object); void lazyAttach(); void rebuildRiggedAttachments( void ); @@ -781,6 +802,7 @@ public: void rebuildHUD(); void resetHUDAttachments(); BOOL canAttachMoreObjects() const; + BOOL canAttachMoreObjects(U32 n) const; protected: U32 getNumAttachments() const; // O(N), not O(1) @@ -788,15 +810,12 @@ protected: // Old/nonstandard/Agent-only functions //-------------------------------------------------------------------- public: - static BOOL detachAttachmentIntoInventory(const LLUUID& item_id); BOOL isWearingAttachment( const LLUUID& inv_item_id ); // testzone attachpt BOOL isWearingUnsupportedAttachment( const LLUUID& inv_item_id ); // LLViewerObject* getWornAttachment( const LLUUID& inv_item_id ); -// [RLVa:KB] - Checked: 2010-03-14 (RLVa-1.2.0a) | Added: RLVa-1.1.0i - LLViewerJointAttachment* getWornAttachmentPoint(const LLUUID& inv_item_id) const; -// [/RLVa:KB] + const std::string getAttachedPointName(const LLUUID& inv_item_id); // @@ -844,7 +863,7 @@ public: void addChat(const LLChat& chat); void clearChat(); void startTyping() { mTyping = TRUE; mTypingTimer.reset(); mIdleTimer.reset();} - void stopTyping() { mTyping = FALSE; } + void stopTyping() { mTyping = FALSE; mIdleTimer.reset();} private: BOOL mVisibleChat; @@ -904,6 +923,9 @@ private: BOOL mStepOnLand; U8 mStepMaterial; LLVector3 mStepObjectVelocity; + +public: + bool mSupportsPhysics; //Client supports v2 wearable physics. Disable emerald physics. //-------------------------------------------------------------------- // Emerald legacy boob bounce @@ -925,10 +947,7 @@ private: LLFrameTimer mBoobBounceTimer; EmeraldAvatarLocalBoobConfig mLocalBoobConfig; EmeraldBoobState mBoobState; - -public: - bool mSupportsPhysics; //Client supports v2 wearable physics. Disable emerald physics. - + /** Physics ** ** *******************************************************************************/ @@ -966,23 +985,21 @@ private: public: std::string getFullname() const; // Returns "FirstName LastName" + std::string avString() const; // Frequently used string in log messages "Avatar '* labels); static void getAnimNames(LLDynamicArray* names); private: - std::string mNameString; - std::string mSubNameString; + std::string mNameString; // UTF-8 title + name + status std::string mTitle; bool mNameAway; bool mNameBusy; bool mNameMute; bool mNameAppearance; - bool mRenderTag; - bool mRenderGroupTitles; - std::string mRenderedName; - std::string mClientName; - std::string mIdleString; - S32 mUsedNameSystem; + bool mNameFriend; + bool mNameCloud; + F32 mNameAlpha; + BOOL mRenderGroupTitles; //-------------------------------------------------------------------- // Display the name (then optionally fade it out) @@ -996,28 +1013,7 @@ private: BOOL mTyping; public: BOOL isTyping(){ return mTyping; } -private: LLFrameTimer mTypingTimer; - static void on_avatar_name_response(const LLUUID& agent_id, const LLAvatarName& av_name, void *userdata); - - //-------------------------------------------------------------------- - // Client tagging - //-------------------------------------------------------------------- -public: - // - void getClientInfo(std::string& clientTag, LLColor4& tagColor, BOOL useComment=FALSE); - std::string extraMetadata; - // - - static bool updateClientTags(); - static bool loadClientTags(); - std::string mClientTag; //Zwagoth's new client identification system. -HgB - LLColor4 mClientColor; //Zwagoth's new client identification system. -HgB - - bool mNameFromChatOverride; - bool mNameFromChatChanged; - std::string mNameFromChatText; - std::string mNameFromAttachment; /** Name ** ** @@ -1071,7 +1067,6 @@ private: //-------------------------------------------------------------------- public: static void dumpArchetypeXML(void*); - static void dumpScratchTextureByteCount(); //Agent only static void dumpBakedStatus(); const std::string getBakedStatusForPrintout() const; void dumpAvatarTEs(const std::string& context) const; @@ -1084,13 +1079,23 @@ protected: S32 getUnbakedPixelAreaRank(); BOOL mHasGrey; private: - LLUUID mSavedTE[ LLVOAvatarDefines::TEX_NUM_INDICES ]; - BOOL mHasBakedHair; F32 mMinPixelArea; F32 mMaxPixelArea; F32 mAdjustedPixelArea; std::string mDebugText; + + //-------------------------------------------------------------------- + // Avatar Rez Metrics + //-------------------------------------------------------------------- +public: + void debugAvatarRezTime(std::string notification_name, std::string comment = ""); + F32 debugGetExistenceTimeElapsedF32() const { return mDebugExistenceTimer.getElapsedTimeF32(); } + +protected: + LLFrameTimer mRuthDebugTimer; // For tracking how long it takes for av to rez + LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory. + /** Diagnostics ** ** *******************************************************************************/ @@ -1112,6 +1117,7 @@ protected: // Shared with LLVOAvatarSelf BOOL parseXmlColorNodes(LLXmlTreeNode* root); BOOL parseXmlLayerNodes(LLXmlTreeNode* root); BOOL parseXmlDriverNodes(LLXmlTreeNode* root); + BOOL parseXmlMorphNodes(LLXmlTreeNode* root); struct LLVOAvatarMeshInfo { @@ -1171,91 +1177,66 @@ protected: // Shared with LLVOAvatarSelf typedef std::vector driver_info_list_t; driver_info_list_t mDriverInfoList; + + struct LLVOAvatarMorphInfo + { + LLVOAvatarMorphInfo() + : mInvert(FALSE) {} + std::string mName; + std::string mRegion; + std::string mLayer; + BOOL mInvert; + }; + + typedef std::vector morph_info_list_t; + morph_info_list_t mMorphMaskInfoList; }; -public: //Public until pulled out of LLTexLayer struct LLMaskedMorph { - LLMaskedMorph(LLPolyMorphTarget *morph_target, BOOL invert) : + LLMaskedMorph(LLPolyMorphTarget *morph_target, BOOL invert, std::string layer) : mMorphTarget(morph_target), - mInvert(invert) + mInvert(invert), + mLayer(layer) { morph_target->addPendingMorphMask(); } LLPolyMorphTarget *mMorphTarget; BOOL mInvert; + std::string mLayer; }; /** Support classes ** ** *******************************************************************************/ - // -public: - //bool mNametagSaysIdle; - //bool mIdleForever; - //LLFrameTimer mIdleTimer; - //U32 mIdleMinutes; - LLUUID mFocusObject; - LLVector3d mFocusVector; - //void resetIdleTime(); -// - +//Avatar idle timer private: - //----------------------------------------------------------------------------------------------- - // Per-avatar information about texture data. - // To-do: Move this to private implementation class - //----------------------------------------------------------------------------------------------- + std::string getIdleTime(bool is_away, bool is_busy, bool is_appearance); +public: + LLFrameTimer mIdleTimer; +private: + S32 mIdleMinute; - struct LocalTextureData - { - LocalTextureData() : mIsBakedReady(false), mDiscard(MAX_DISCARD_LEVEL+1), mImage(NULL) - {} - LLPointer mImage; - bool mIsBakedReady; - S32 mDiscard; - }; - typedef std::map localtexture_map_t; - localtexture_map_t mLocalTextureData; +//CCS Nametag +public: + void setNameFromChat(const std::string &text); + void clearNameFromChat(); +private: + void idleCCSUpdateAttachmentText(bool render_name); + LLFrameTimer mCCSUpdateAttachmentTimer; + std::string mCCSAttachmentText; + bool mCCSChatTextOverride; + std::string mCCSChatText; +// +}; // LLVOAvatar - //-------------------------------------------------------------------- - // Private member variables. - //-------------------------------------------------------------------- - // Scratch textures used for compositing - static LLMap< LLGLenum, LLGLuint*> sScratchTexNames; - static LLMap< LLGLenum, F32*> sScratchTexLastBindTime; - static S32 sScratchTexBytes; - - static LLSD sClientResolutionList; - - bool isUnknownClient(); - static void resolveClient(LLColor4& avatar_name_color, std::string& client, LLVOAvatar* avatar); - friend class LLFloaterAvatarList; - - - U64 mLastRegionHandle; - LLFrameTimer mRegionCrossingTimer; - S32 mRegionCrossingCount; - - static bool sDoProperArc; -}; - -//----------------------------------------------------------------------------------------------- -// Inlines -//----------------------------------------------------------------------------------------------- -inline BOOL LLVOAvatar::isTextureDefined(U8 te) const -{ - return (getTEImage(te)->getID() != IMG_DEFAULT_AVATAR && getTEImage(te)->getID() != IMG_DEFAULT); -} - -inline BOOL LLVOAvatar::isTextureVisible(U8 te) const -{ - return ((isTextureDefined(te) || isSelf()) - && (getTEImage(te)->getID() != IMG_INVISIBLE - || LLDrawPoolAlpha::sShowDebugAlpha)); -} +extern const F32 SELF_ADDITIONAL_PRI; +extern const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL; +extern const U32 EMERALD_BOOB_SIZE_PARAM; //"Breast Size" +extern const U32 EMERALD_BOOB_GRAVITY_PARAM; //"Breast_Gravity" #endif // LL_VO_AVATAR_H diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index ce1077c9c..fdfc565e3 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -23,6 +23,13 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ + +#if LL_MSVC +// disable warning about boost::lexical_cast returning uninitialized data +// when it fails to parse the string +#pragma warning (disable:4701) +#endif + #include "llviewerprecompiledheaders.h" #include "llvoavatarself.h" @@ -35,11 +42,13 @@ #include "llagentwearables.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" +#include "llinventoryfunctions.h" #include "llnotificationsutil.h" #include "llselectmgr.h" #include "lltoolgrab.h" // for needsRenderBeam #include "lltoolmgr.h" // for needsRenderBeam #include "lltoolmorph.h" +#include "lltrans.h" #include "llviewercamera.h" #include "llviewercontrol.h" #include "llviewermedia.h" @@ -47,16 +56,74 @@ #include "llviewerobjectlist.h" #include "llviewerstats.h" #include "llviewerregion.h" +#include "llappearancemgr.h" #include "llmeshrepository.h" #include "llvovolume.h" -LLVOAvatarSelf *gAgentAvatarp = NULL; +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) +#include "rlvhandler.h" +#include "rlvlocks.h" +// [/RLVa:KB] + +#if LL_MSVC +// disable boost::lexical_cast warning +#pragma warning (disable:4702) +#endif + +#include + +LLPointer gAgentAvatarp = NULL; + BOOL isAgentAvatarValid() { - return (gAgentAvatarp && + return (gAgentAvatarp.notNull() && (gAgentAvatarp->getRegion() != NULL) && (!gAgentAvatarp->isDead())); } +using namespace LLVOAvatarDefines; + +/********************************************************************************* + ** ** + ** Begin private LLVOAvatarSelf Support classes + ** + **/ + +struct LocalTextureData +{ + LocalTextureData() : + mIsBakedReady(false), + mDiscard(MAX_DISCARD_LEVEL+1), + mImage(NULL), + mWearableID(IMG_DEFAULT_AVATAR), + mTexEntry(NULL) + {} + LLPointer mImage; + bool mIsBakedReady; + S32 mDiscard; + LLUUID mWearableID; // UUID of the wearable that this texture belongs to, not of the image itself + LLTextureEntry *mTexEntry; +}; + +//----------------------------------------------------------------------------- +// Callback data +//----------------------------------------------------------------------------- + + +/** + ** + ** End LLVOAvatarSelf Support classes + ** ** + *********************************************************************************/ + + +//----------------------------------------------------------------------------- +// Static Data +//----------------------------------------------------------------------------- +S32 LLVOAvatarSelf::sScratchTexBytes = 0; +LLMap< LLGLenum, LLGLuint*> LLVOAvatarSelf::sScratchTexNames; +LLMap< LLGLenum, F32*> LLVOAvatarSelf::sScratchTexLastBindTime; + + /********************************************************************************* ** ** ** Begin LLVOAvatarSelf Constructor routines @@ -69,13 +136,16 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id, LLVOAvatar(id, pcode, regionp), mScreenp(NULL), mLastRegionHandle(0), - mRegionCrossingCount(0) + mRegionCrossingCount(0), + mInitialBakesLoaded(false) { gAgentWearables.setAvatarObject(this); gAgentCamera.setAvatarObject(this); mMotionController.mIsSelf = TRUE; + SHClientTagMgr::instance().updateAvatarTag(this); //No TE update messages for self. Force update here. + lldebugs << "Marking avatar as self " << id << llendl; } @@ -89,7 +159,7 @@ void LLVOAvatarSelf::initInstance() LLVOAvatar::initInstance(); llinfos << "Self avatar object created. Starting timer." << llendl; - /*mDebugSelfLoadTimer.reset(); + mDebugSelfLoadTimer.reset(); // clear all times to -1 for debugging for (U32 i =0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i) { @@ -103,7 +173,12 @@ void LLVOAvatarSelf::initInstance() { mDebugBakedTextureTimes[i][0] = -1.0f; mDebugBakedTextureTimes[i][1] = -1.0f; - }*/ + mInitialBakeIDs[i] = LLUUID::null; + } + +// [RLVa:KB] - Checked: 2010-12-12 (RLVa-1.2.2c) | Added: RLVa-1.2.2c + RlvAttachPtLookup::initLookupTable(); +// [/RLVa:KB] status &= buildMenus(); if (!status) @@ -123,6 +198,21 @@ void LLVOAvatarSelf::markDead() /*virtual*/ BOOL LLVOAvatarSelf::loadAvatar() { BOOL success = LLVOAvatar::loadAvatar(); + + // set all parameters sotred directly in the avatar to have + // the isSelfParam to be TRUE - this is used to prevent + // them from being animated or trigger accidental rebakes + // when we copy params from the wearable to the base avatar. + for (LLViewerVisualParam* param = (LLViewerVisualParam*) getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) getNextVisualParam()) + { + if (param->getWearableType() != LLWearableType::WT_INVALID) + { + param->setIsDummy(TRUE); + } + } + return success; } @@ -213,7 +303,7 @@ BOOL LLVOAvatarSelf::buildMenus() // object_selected_and_point_valid); item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", iter->first); - gAttachPieMenu->append(item); + gAttachPieMenu->addChild(item); attachment_found = TRUE; break; @@ -221,15 +311,9 @@ BOOL LLVOAvatarSelf::buildMenus() } } - - - - - - if (!attachment_found) { - gAttachPieMenu->appendSeparator(); + gAttachPieMenu->addSeparator(); } } @@ -247,7 +331,7 @@ BOOL LLVOAvatarSelf::buildMenus() LLViewerJointAttachment* attachment = iter->second; if (attachment->getGroup() == i) { - gDetachPieMenu->append(new LLMenuItemCallGL(attachment->getName(), + gDetachPieMenu->addChild(new LLMenuItemCallGL(attachment->getName(), &handle_detach_from_avatar, object_attached, attachment)); attachment_found = TRUE; @@ -257,7 +341,7 @@ BOOL LLVOAvatarSelf::buildMenus() if (!attachment_found) { - gDetachPieMenu->appendSeparator(); + gDetachPieMenu->addSeparator(); } } } @@ -281,16 +365,19 @@ BOOL LLVOAvatarSelf::buildMenus() // NULL, // object_selected_and_point_valid); item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", iter->first); - gAttachScreenPieMenu->append(item); - gDetachScreenPieMenu->append(new LLMenuItemCallGL(attachment->getName(), + gAttachScreenPieMenu->addChild(item); + gDetachScreenPieMenu->addChild(new LLMenuItemCallGL(attachment->getName(), &handle_detach_from_avatar, object_attached, attachment)); } } - - for (S32 pass = 0; pass < 2; pass++) { + // *TODO: Skinning - gAttachSubMenu is an awful, awful hack + if (!gAttachSubMenu) + { + break; + } for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) @@ -305,17 +392,17 @@ BOOL LLVOAvatarSelf::buildMenus() NULL, &object_selected_and_point_valid, &attach_label, attachment); item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", iter->first); - gAttachSubMenu->append(item); + gAttachSubMenu->addChild(item); - gDetachSubMenu->append(new LLMenuItemCallGL(attachment->getName(), + gDetachSubMenu->addChild(new LLMenuItemCallGL(attachment->getName(), &handle_detach_from_avatar, object_attached, &detach_label, attachment)); } if (pass == 0) { // put separator between non-hud and hud attachments - gAttachSubMenu->appendSeparator(); - gDetachSubMenu->appendSeparator(); + gAttachSubMenu->addSeparator(); + gDetachSubMenu->addSeparator(); } } @@ -352,8 +439,8 @@ BOOL LLVOAvatarSelf::buildMenus() S32 attach_index = attach_it->second; while (cur_pie_slice < requested_pie_slice) { - gAttachBodyPartPieMenus[group]->appendSeparator(); - gDetachBodyPartPieMenus[group]->appendSeparator(); + gAttachBodyPartPieMenus[group]->addSeparator(); + gDetachBodyPartPieMenus[group]->addSeparator(); cur_pie_slice++; } @@ -367,15 +454,18 @@ BOOL LLVOAvatarSelf::buildMenus() // [/RLVa:KB] // LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), // NULL, object_selected_and_point_valid); - gAttachBodyPartPieMenus[group]->append(item); + gAttachBodyPartPieMenus[group]->addChild(item); item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", attach_index); - gDetachBodyPartPieMenus[group]->append(new LLMenuItemCallGL(attachment->getName(), + gDetachBodyPartPieMenus[group]->addChild(new LLMenuItemCallGL(attachment->getName(), &handle_detach_from_avatar, object_attached, attachment)); cur_pie_slice++; } } } + + init_meshes_and_morphs_menu(); + return TRUE; } @@ -391,6 +481,78 @@ LLVOAvatarSelf::~LLVOAvatarSelf() { cleanup(); } + +/** + ** + ** End LLVOAvatarSelf Constructor routines + ** ** + *********************************************************************************/ + +//virtual +BOOL LLVOAvatarSelf::loadLayersets() +{ + BOOL success = TRUE; + for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator iter = sAvatarXmlInfo->mLayerInfoList.begin(); + iter != sAvatarXmlInfo->mLayerInfoList.end(); + ++iter) + { + // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. + const LLTexLayerSetInfo *info = *iter; + LLTexLayerSet* layer_set = new LLTexLayerSet( this ); + + if (!layer_set->setInfo(info)) + { + stop_glerror(); + delete layer_set; + llwarns << "avatar file: layer_set->parseData() failed" << llendl; + return FALSE; + } + + // scan baked textures and associate the layerset with the appropriate one + EBakedTextureIndex baked_index = BAKED_NUM_INDICES; + for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; + if (layer_set->isBodyRegion(baked_dict->mName)) + { + baked_index = baked_iter->first; + // ensure both structures are aware of each other + mBakedTextureDatas[baked_index].mTexLayerSet = layer_set; + layer_set->setBakedTexIndex(baked_index); + break; + } + } + // if no baked texture was found, warn and cleanup + if (baked_index == BAKED_NUM_INDICES) + { + llwarns << " has invalid body_region attribute" << llendl; + delete layer_set; + return FALSE; + } + + // scan morph masks and let any affected layers know they have an associated morph + for (LLVOAvatar::morph_list_t::const_iterator morph_iter = mBakedTextureDatas[baked_index].mMaskedMorphs.begin(); + morph_iter != mBakedTextureDatas[baked_index].mMaskedMorphs.end(); + ++morph_iter) + { + LLMaskedMorph *morph = *morph_iter; + LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer); + if (layer) + { + layer->setHasMorph(TRUE); + } + else + { + llwarns << "Could not find layer named " << morph->mLayer << " to set morph flag" << llendl; + success = FALSE; + } + } + } + return success; +} +// virtual BOOL LLVOAvatarSelf::updateCharacter(LLAgent &agent) { LLMemType mt(LLMemType::MTYPE_AVATAR); @@ -415,7 +577,7 @@ BOOL LLVOAvatarSelf::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { return TRUE; } - if(!gNoRender) + /*if(!gNoRender) { //Emerald performs some force-bakes stuff here. Added it in because we noticed slow responses with client tag ident. -HgB for(U8 i=0;iforceActive(); } - } + }*/ LLVOAvatar::idleUpdate(agent,world,time); if(!gNoRender) idleUpdateTractorBeam(); @@ -445,6 +607,91 @@ void LLVOAvatarSelf::resetJointPositions( void ) { return LLVOAvatar::resetJointPositions(); } +// virtual +BOOL LLVOAvatarSelf::setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake ) +{ + if (!which_param) + { + return FALSE; + } + LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(which_param->getID()); + return setParamWeight(param,weight,upload_bake); +} + +// virtual +BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake ) +{ + if (!param_name) + { + return FALSE; + } + LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(param_name); + return setParamWeight(param,weight,upload_bake); +} + +// virtual +BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake ) +{ + LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(index); + return setParamWeight(param,weight,upload_bake); +} + +BOOL LLVOAvatarSelf::setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake ) +{ + if (!param) + { + return FALSE; + } + + if (param->getCrossWearable()) + { + LLWearableType::EType type = (LLWearableType::EType)param->getWearableType(); + U32 size = gAgentWearables.getWearableCount(type); + for (U32 count = 0; count < size; ++count) + { + LLWearable *wearable = gAgentWearables.getWearable(type,count); + if (wearable) + { + wearable->setVisualParamWeight(param->getID(), weight, upload_bake); + } + } + } + + if(param->getID() == EMERALD_BOOB_GRAVITY_PARAM && weight != getActualBoobGrav()) + { + setActualBoobGrav(weight); + } + + return LLCharacter::setVisualParamWeight(param,weight,upload_bake); +} + +/*virtual*/ +void LLVOAvatarSelf::updateVisualParams() +{ + LLVOAvatar::updateVisualParams(); +} + +/*virtual*/ +void LLVOAvatarSelf::idleUpdateAppearanceAnimation() +{ + // Animate all top-level wearable visual parameters + gAgentWearables.animateAllWearableParams(calcMorphAmount(), FALSE); + + // apply wearable visual params to avatar + for (U32 type = 0; type < LLWearableType::WT_COUNT; type++) + { + LLWearable *wearable = gAgentWearables.getTopWearable((LLWearableType::EType)type); + if (wearable) + { + wearable->writeToAvatar(); + } + } + + //allow avatar to process updates + LLVOAvatar::idleUpdateAppearanceAnimation(); + +} + // virtual void LLVOAvatarSelf::requestStopMotion(LLMotion* motion) { @@ -469,6 +716,63 @@ void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id) object->mFlags &= ~FLAGS_ANIM_SOURCE; } } + +//virtual +U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys, + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp) +{ + U32 retval = LLVOAvatar::processUpdateMessage(mesgsys,user_data,block_num,update_type,dp); + + if (mInitialBakesLoaded == false && retval == 0x0) + { + // call update textures to force the images to be created + updateMeshTextures(); + + // unpack the texture UUIDs to the texture slots + retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num); + + // need to trigger a few operations to get the avatar to use the new bakes + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + const LLVOAvatarDefines::ETextureIndex te = mBakedTextureDatas[i].mTextureIndex; + LLUUID texture_id = getTEImage(te)->getID(); + setNewBakedTexture(te, texture_id); + mInitialBakeIDs[i] = texture_id; + } + + onFirstTEMessageReceived(); + + mInitialBakesLoaded = true; + } + + return retval; +} + +void LLVOAvatarSelf::setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index) +{ + if (te >= TEX_NUM_INDICES) + { + llassert(0); + return; + } + + if (getTEImage(te)->getID() == image->getID()) + { + return; + } + + if (isIndexBakedTexture((ETextureIndex)te)) + { + llassert(0); + return; + } + + setTEImage(te, image); +} + //virtual void LLVOAvatarSelf::removeMissingBakedTextures() { @@ -494,8 +798,9 @@ void LLVOAvatarSelf::removeMissingBakedTextures() if (removed) { - for(U32 i = 0; i < mBakedTextureDatas.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { + mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(TRUE); invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, FALSE); } updateMeshTextures(); @@ -652,6 +957,1674 @@ void LLVOAvatarSelf::restoreMeshData() // force mesh update as LOD might not have changed to trigger this gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); } + + + +//----------------------------------------------------------------------------- +// updateAttachmentVisibility() +//----------------------------------------------------------------------------- +void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode) +{ + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (attachment->getIsHUDAttachment()) + { + attachment->setAttachmentVisibility(TRUE); + } + else + { + switch (camera_mode) + { + case CAMERA_MODE_MOUSELOOK: + if (LLVOAvatar::sVisibleInFirstPerson && attachment->getVisibleInFirstPerson()) + { + attachment->setAttachmentVisibility(TRUE); + } + else + { + attachment->setAttachmentVisibility(FALSE); + } + break; + default: + attachment->setAttachmentVisibility(TRUE); + break; + } + } + } +} + +/*virtual*/ BOOL LLVOAvatarSelf::isWearingWearableType(LLWearableType::EType type ) const +{ + return gAgentWearables.getWearableCount(type) > 0; +} + +//----------------------------------------------------------------------------- +// updatedWearable( LLWearableType::EType type ) +// forces an update to any baked textures relevant to type. +// will force an upload of the resulting bake if the second parameter is TRUE +//----------------------------------------------------------------------------- +void LLVOAvatarSelf::wearableUpdated( LLWearableType::EType type, BOOL upload_result ) +{ + for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; + const LLVOAvatarDefines::EBakedTextureIndex index = baked_iter->first; + + if (baked_dict) + { + for (LLVOAvatarDefines::wearables_vec_t::const_iterator type_iter = baked_dict->mWearables.begin(); + type_iter != baked_dict->mWearables.end(); + ++type_iter) + { + const LLWearableType::EType comp_type = *type_iter; + if (comp_type == type) + { + if (mBakedTextureDatas[index].mTexLayerSet) + { + mBakedTextureDatas[index].mTexLayerSet->setUpdatesEnabled(true); + invalidateComposite(mBakedTextureDatas[index].mTexLayerSet, upload_result); + } + break; + } + } + } + } + + // Physics type has no associated baked textures, but change of params needs to be sent to + // other avatars. + if (type == LLWearableType::WT_PHYSICS) + { + gAgent.sendAgentSetAppearance(); + } +} + +//----------------------------------------------------------------------------- +// isWearingAttachment() +//----------------------------------------------------------------------------- +BOOL LLVOAvatarSelf::isWearingAttachment(const LLUUID& inv_item_id) const +{ + const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id); + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + const LLViewerJointAttachment* attachment = iter->second; + if (attachment->getAttachedObject(base_inv_item_id)) + { + return TRUE; + } + } + return FALSE; +} + +//----------------------------------------------------------------------------- +BOOL LLVOAvatarSelf::attachmentWasRequested(const LLUUID& inv_item_id) const +{ + const F32 REQUEST_EXPIRATION_SECONDS = 5.0; // any request older than this is ignored/removed. + std::map::iterator it = mAttachmentRequests.find(inv_item_id); + if (it != mAttachmentRequests.end()) + { + const LLTimer& request_time = it->second; + F32 request_time_elapsed = request_time.getElapsedTimeF32(); + if (request_time_elapsed > REQUEST_EXPIRATION_SECONDS) + { + mAttachmentRequests.erase(it); + return FALSE; + } + else + { + return TRUE; + } + } + else + { + return FALSE; + } +} + +//----------------------------------------------------------------------------- +void LLVOAvatarSelf::addAttachmentRequest(const LLUUID& inv_item_id) +{ + LLTimer current_time; + mAttachmentRequests[inv_item_id] = current_time; +} + +//----------------------------------------------------------------------------- +void LLVOAvatarSelf::removeAttachmentRequest(const LLUUID& inv_item_id) +{ + mAttachmentRequests.erase(inv_item_id); +} + +//----------------------------------------------------------------------------- +// getWornAttachment() +//----------------------------------------------------------------------------- +LLViewerObject* LLVOAvatarSelf::getWornAttachment(const LLUUID& inv_item_id) +{ + const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id); + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (LLViewerObject *attached_object = attachment->getAttachedObject(base_inv_item_id)) + { + return attached_object; + } + } + return NULL; +} + +// [RLVa:KB] - Checked: 2010-03-14 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a +LLViewerJointAttachment* LLVOAvatarSelf::getWornAttachmentPoint(const LLUUID& idItem) const +{ + const LLUUID& idItemBase = gInventory.getLinkedItemID(idItem); + for (attachment_map_t::const_iterator itAttachPt = mAttachmentPoints.begin(); itAttachPt != mAttachmentPoints.end(); ++itAttachPt) + { + LLViewerJointAttachment* pAttachPt = itAttachPt->second; + if (pAttachPt->getAttachedObject(idItemBase)) + return pAttachPt; + } + return NULL; +} +// [/RLVa:KB] + +const std::string LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id) const +{ + const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id); + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + const LLViewerJointAttachment* attachment = iter->second; + if (attachment->getAttachedObject(base_inv_item_id)) + { + return attachment->getName(); + } + } + + return LLStringUtil::null; +} + +//virtual +const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_object) +{ + const LLViewerJointAttachment *attachment = LLVOAvatar::attachObject(viewer_object); + if (!attachment) + { + return 0; + } + + updateAttachmentVisibility(gAgentCamera.getCameraMode()); + + // Then make sure the inventory is in sync with the avatar. + + // Should just be the last object added + if (attachment->isObjectAttached(viewer_object)) + { + const LLUUID& attachment_id = viewer_object->getAttachmentItemID(); + LLAppearanceMgr::instance().registerAttachment(attachment_id); + // Clear any pending requests once the attachment arrives. + removeAttachmentRequest(attachment_id); + updateLODRiggedAttachments(); + +// [RLVa:KB] - Checked: 2010-08-22 (RLVa-1.2.1a) | Modified: RLVa-1.2.1a + // NOTE: RLVa event handlers should be invoked *after* LLVOAvatar::attachObject() calls LLViewerJointAttachment::addObject() + if (rlv_handler_t::isEnabled()) + { + RlvAttachmentLockWatchdog::instance().onAttach(viewer_object, attachment); + gRlvHandler.onAttach(viewer_object, attachment); + + if ( (attachment->getIsHUDAttachment()) && (!gRlvAttachmentLocks.hasLockedHUD()) ) + gRlvAttachmentLocks.updateLockedHUD(); + } +// [/RLVa:KB] + } + + return attachment; +} + +//virtual +BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object) +{ + const LLUUID attachment_id = viewer_object->getAttachmentItemID(); + +// [RLVa:KB] - Checked: 2010-03-05 (RLVa-1.2.0a) | Added: RLVa-1.2.0a + // NOTE: RLVa event handlers should be invoked *before* LLVOAvatar::detachObject() calls LLViewerJointAttachment::removeObject() + if (rlv_handler_t::isEnabled()) + { + for (attachment_map_t::const_iterator itAttachPt = mAttachmentPoints.begin(); itAttachPt != mAttachmentPoints.end(); ++itAttachPt) + { + const LLViewerJointAttachment* pAttachPt = itAttachPt->second; + if (pAttachPt->isObjectAttached(viewer_object)) + { + RlvAttachmentLockWatchdog::instance().onDetach(viewer_object, pAttachPt); + gRlvHandler.onDetach(viewer_object, pAttachPt); + } + } + } +// [/RLVa:KB] + + if ( LLVOAvatar::detachObject(viewer_object) ) + { + LLVOAvatar::cleanupAttachedMesh( viewer_object ); + + // the simulator should automatically handle permission revocation + + stopMotionFromSource(attachment_id); + LLFollowCamMgr::setCameraActive(viewer_object->getID(), FALSE); + + LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); + ++iter) + { + LLViewerObject* child_objectp = *iter; + // the simulator should automatically handle + // permissions revocation + + stopMotionFromSource(child_objectp->getID()); + LLFollowCamMgr::setCameraActive(child_objectp->getID(), FALSE); + } + + // Make sure the inventory is in sync with the avatar. + + // Update COF contents, don't trigger appearance update. + if (!isAgentAvatarValid()) + { + llinfos << "removeItemLinks skipped, avatar is under destruction" << llendl; + } + else + { + LLAppearanceMgr::instance().unregisterAttachment(attachment_id); + } + +// [RLVa:KB] - Checked: 2010-08-22 (RLVa-1.2.1a) | Added: RLVa-1.2.1a + if ( (rlv_handler_t::isEnabled()) && (viewer_object->isHUDAttachment()) && (gRlvAttachmentLocks.hasLockedHUD()) ) + gRlvAttachmentLocks.updateLockedHUD(); +// [/RLVa:KB] + + return TRUE; + } + return FALSE; +} + +// static +BOOL LLVOAvatarSelf::detachAttachmentIntoInventory(const LLUUID &item_id) +{ + LLInventoryItem* item = gInventory.getItem(item_id); +// if (item) +// [RLVa:KB] - Checked: 2010-09-04 (RLVa-1.2.1c) | Added: RLVa-1.2.1c + if ( (item) && ((!rlv_handler_t::isEnabled()) || (gRlvAttachmentLocks.canDetach(item))) ) +// [/RLVa:KB] + { + gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id); + gMessageSystem->sendReliable(gAgent.getRegion()->getHost()); + + // This object might have been selected, so let the selection manager know it's gone now + LLViewerObject *found_obj = gObjectList.findObject(item_id); + if (found_obj) + { + LLSelectMgr::getInstance()->remove(found_obj); + } + + // Error checking in case this object was attached to an invalid point + // In that case, just remove the item from COF preemptively since detach + // will fail. + if (isAgentAvatarValid()) + { + const LLViewerObject *attached_obj = gAgentAvatarp->getWornAttachment(item_id); + if (!attached_obj) + { + LLAppearanceMgr::instance().removeCOFItemLinks(item_id, false); + } + } + return TRUE; + } + return FALSE; +} + +U32 LLVOAvatarSelf::getNumWearables(LLVOAvatarDefines::ETextureIndex i) const +{ + LLWearableType::EType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i); + return gAgentWearables.getWearableCount(type); +} + +// virtual +void LLVOAvatarSelf::localTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src_raw, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) +{ + + const LLUUID& src_id = src_vi->getID(); + LLAvatarTexData *data = (LLAvatarTexData *)userdata; + ETextureIndex index = data->mIndex; + if (!isIndexLocalTexture(index)) return; + + LLLocalTextureObject *local_tex_obj = getLocalTextureObject(index, 0); + + // fix for EXT-268. Preventing using of NULL pointer + if(NULL == local_tex_obj) + { + LL_WARNS("TAG") << "There is no Local Texture Object with index: " << index + << ", final: " << final + << LL_ENDL; + return; + } + if (success) + { + if (!local_tex_obj->getBakedReady() && + local_tex_obj->getImage() != NULL && + (local_tex_obj->getID() == src_id) && + discard_level < local_tex_obj->getDiscard()) + { + local_tex_obj->setDiscard(discard_level); + if (isUsingBakedTextures()) + { + requestLayerSetUpdate(index); + } + else + { + LLVisualParamHint::requestHintUpdates(); + } + updateMeshTextures(); + } + } + else if (final) + { + // Failed: asset is missing + if (!local_tex_obj->getBakedReady() && + local_tex_obj->getImage() != NULL && + local_tex_obj->getImage()->getID() == src_id) + { + local_tex_obj->setDiscard(0); + requestLayerSetUpdate(index); + updateMeshTextures(); + } + } +} + +// virtual +BOOL LLVOAvatarSelf::getLocalTextureGL(ETextureIndex type, LLViewerTexture** tex_pp, U32 index) const +{ + *tex_pp = NULL; + + if (!isIndexLocalTexture(type)) return FALSE; + if (getLocalTextureID(type, index) == IMG_DEFAULT_AVATAR) return TRUE; + + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index); + if (!local_tex_obj) + { + return FALSE; + } + *tex_pp = local_tex_obj->getImage(); + return TRUE; +} + +LLViewerFetchedTexture* LLVOAvatarSelf::getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, U32 index) const +{ + if (!isIndexLocalTexture(type)) + { + return NULL; + } + + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index); + if (!local_tex_obj) + { + return NULL; + } + if (local_tex_obj->getID() == IMG_DEFAULT_AVATAR) + { + return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); + } + return local_tex_obj->getImage(); +} + +const LLUUID& LLVOAvatarSelf::getLocalTextureID(ETextureIndex type, U32 index) const +{ + if (!isIndexLocalTexture(type)) return IMG_DEFAULT_AVATAR; + + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index); + if (local_tex_obj && local_tex_obj->getImage() != NULL) + { + return local_tex_obj->getImage()->getID(); + } + return IMG_DEFAULT_AVATAR; +} + + +//----------------------------------------------------------------------------- +// isLocalTextureDataAvailable() +// Returns true if at least the lowest quality discard level exists for every texture +// in the layerset. +//----------------------------------------------------------------------------- +BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLTexLayerSet* layerset) const +{ + /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) + return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ + for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const EBakedTextureIndex baked_index = baked_iter->first; + if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) + { + BOOL ret = true; + const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + ret &= (getLocalDiscardLevel(tex_index, wearable_index) >= 0); + } + } + return ret; + } + } + llassert(0); + return FALSE; +} + +//----------------------------------------------------------------------------- +// virtual +// isLocalTextureDataFinal() +// Returns true if the highest quality discard level exists for every texture +// in the layerset. +//----------------------------------------------------------------------------- +BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLTexLayerSet* layerset) const +{ + const U32 desired_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); + // const U32 desired_tex_discard_level = 0; // hack to not bake textures on lower discard levels. + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + if (layerset == mBakedTextureDatas[i].mTexLayerSet) + { + const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + if (getLocalDiscardLevel(*local_tex_iter, wearable_index) > (S32)(desired_tex_discard_level)) + { + return FALSE; + } + } + } + return TRUE; + } + } + llassert(0); + return FALSE; +} + +BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const +{ + const U32 desired_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); + // const U32 desired_tex_discard_level = 0; // hack to not bake textures on lower discard levels + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + if (getLocalDiscardLevel(*local_tex_iter, wearable_index) > (S32)(desired_tex_discard_level)) + { + return FALSE; + } + } + } + } + return TRUE; +} + +BOOL LLVOAvatarSelf::isBakedTextureFinal(const LLVOAvatarDefines::EBakedTextureIndex index) const +{ + const LLTexLayerSet *layerset = mBakedTextureDatas[index].mTexLayerSet; + if (!layerset) return FALSE; + const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); + if (!layerset_buffer) return FALSE; + return !layerset_buffer->uploadNeeded(); +} + +BOOL LLVOAvatarSelf::isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const +{ + LLUUID id; + BOOL isDefined = TRUE; + if (isIndexLocalTexture(type)) + { + const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(type); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + if (index >= wearable_count) + { + // invalid index passed in. check all textures of a given type + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + id = getLocalTextureID(type, wearable_index); + isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT); + } + } + else + { + id = getLocalTextureID(type, index); + isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT); + } + } + else + { + id = getTEImage(type)->getID(); + isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT); + } + + return isDefined; +} + +//virtual +BOOL LLVOAvatarSelf::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index) const +{ + if (isIndexBakedTexture(type)) + { + return LLVOAvatar::isTextureVisible(type, (U32)0); + } + + LLUUID tex_id = getLocalTextureID(type,index); + return (tex_id != IMG_INVISIBLE) + || (LLDrawPoolAlpha::sShowDebugAlpha); +} + +//virtual +BOOL LLVOAvatarSelf::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const +{ + if (isIndexBakedTexture(type)) + { + return LLVOAvatar::isTextureVisible(type); + } + + U32 index = gAgentWearables.getWearableIndex(wearable); + return isTextureVisible(type,index); +} + + +//----------------------------------------------------------------------------- +// requestLayerSetUploads() +//----------------------------------------------------------------------------- +void LLVOAvatarSelf::requestLayerSetUploads() +{ + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + requestLayerSetUpload((EBakedTextureIndex)i); + } +} + +void LLVOAvatarSelf::requestLayerSetUpload(LLVOAvatarDefines::EBakedTextureIndex i) +{ + ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex; + const BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index)); + if (!layer_baked && mBakedTextureDatas[i].mTexLayerSet) + { + mBakedTextureDatas[i].mTexLayerSet->requestUpload(); + } +} + +bool LLVOAvatarSelf::areTexturesCurrent() const +{ + return !hasPendingBakedUploads() && gAgentWearables.areWearablesLoaded(); +} + +// virtual +bool LLVOAvatarSelf::hasPendingBakedUploads() const +{ + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + LLTexLayerSet* layerset = mBakedTextureDatas[i].mTexLayerSet; + if (layerset && layerset->getComposite() && layerset->getComposite()->uploadPending()) + { + return true; + } + } + return false; +} + +void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result ) +{ + if( !layerset || !layerset->getUpdatesEnabled() ) + { + return; + } + // llinfos << "LLVOAvatar::invalidComposite() " << layerset->getBodyRegionName() << llendl; + + layerset->requestUpdate(); + layerset->invalidateMorphMasks(); + + if( upload_result ) + { + llassert(isSelf()); + + ETextureIndex baked_te = getBakedTE( layerset ); + setTEImage( baked_te, LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR) ); + layerset->requestUpload(); + updateMeshTextures(); + } +} + +void LLVOAvatarSelf::invalidateAll() +{ + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, TRUE); + } + //mDebugSelfLoadTimer.reset(); +} + +//----------------------------------------------------------------------------- +// setCompositeUpdatesEnabled() +//----------------------------------------------------------------------------- +void LLVOAvatarSelf::setCompositeUpdatesEnabled( bool b ) +{ + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + setCompositeUpdatesEnabled(i, b); + } +} + +void LLVOAvatarSelf::setCompositeUpdatesEnabled(U32 index, bool b) +{ + if (mBakedTextureDatas[index].mTexLayerSet ) + { + mBakedTextureDatas[index].mTexLayerSet->setUpdatesEnabled( b ); + } +} + +bool LLVOAvatarSelf::isCompositeUpdateEnabled(U32 index) +{ + if (mBakedTextureDatas[index].mTexLayerSet) + { + return mBakedTextureDatas[index].mTexLayerSet->getUpdatesEnabled(); + } + return false; +} + +void LLVOAvatarSelf::setupComposites() +{ + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex; + BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index)); + if (mBakedTextureDatas[i].mTexLayerSet) + { + mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(!layer_baked); + } + } +} + +void LLVOAvatarSelf::updateComposites() +{ + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + if (mBakedTextureDatas[i].mTexLayerSet + && ((i != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT))) + { + mBakedTextureDatas[i].mTexLayerSet->updateComposite(); + } + } +} + +// virtual +S32 LLVOAvatarSelf::getLocalDiscardLevel(ETextureIndex type, U32 wearable_index) const +{ + if (!isIndexLocalTexture(type)) return FALSE; + + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, wearable_index); + if (local_tex_obj) + { + if (type >= 0 + && local_tex_obj->getID() != IMG_DEFAULT_AVATAR + && !local_tex_obj->getImage()->isMissingAsset()) + { + return local_tex_obj->getImage()->getDiscardLevel(); + } + else + { + // We don't care about this (no image associated with the layer) treat as fully loaded. + return 0; + } + } + return 0; +} + +// virtual +// Counts the memory footprint of local textures. +void LLVOAvatarSelf::getLocalTextureByteCount(S32* gl_bytes) const +{ + *gl_bytes = 0; + for (S32 type = 0; type < TEX_NUM_INDICES; type++) + { + if (!isIndexLocalTexture((ETextureIndex)type)) continue; + U32 max_tex = getNumWearables((ETextureIndex) type); + for (U32 num = 0; num < max_tex; num++) + { + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject((ETextureIndex) type, num); + if (local_tex_obj) + { + const LLViewerFetchedTexture* image_gl = local_tex_obj->getImage(); + if (image_gl) + { + S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); + + if (image_gl->hasGLTexture()) + { + *gl_bytes += bytes; + } + } + } + } + } +} + +// virtual +void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_tex, BOOL baked_version_ready, U32 index) +{ + if (!isIndexLocalTexture(type)) return; + + LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(src_tex, TRUE) ; + if(!tex) + { + return ; + } + + S32 desired_discard = isSelf() ? 0 : 2; + LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index); + if (!local_tex_obj) + { + if (type >= TEX_NUM_INDICES) + { + llerrs << "Tried to set local texture with invalid type: (" << (U32) type << ", " << index << ")" << llendl; + return; + } + LLWearableType::EType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType(type); + if (!gAgentWearables.getWearable(wearable_type,index)) + { + // no wearable is loaded, cannot set the texture. + return; + } + gAgentWearables.addLocalTextureObject(wearable_type,type,index); + local_tex_obj = getLocalTextureObject(type,index); + if (!local_tex_obj) + { + llerrs << "Unable to create LocalTextureObject for wearable type & index: (" << (U32) wearable_type << ", " << index << ")" << llendl; + return; + } + + LLTexLayerSet *layer_set = getLayerSet(type); + if (layer_set) + { + layer_set->cloneTemplates(local_tex_obj, type, gAgentWearables.getWearable(wearable_type,index)); + } + + } + if (!baked_version_ready) + { + if (tex != local_tex_obj->getImage() || local_tex_obj->getBakedReady()) + { + local_tex_obj->setDiscard(MAX_DISCARD_LEVEL+1); + } + if (tex->getID() != IMG_DEFAULT_AVATAR) + { + if (local_tex_obj->getDiscard() > desired_discard) + { + S32 tex_discard = tex->getDiscardLevel(); + if (tex_discard >= 0 && tex_discard <= desired_discard) + { + local_tex_obj->setDiscard(tex_discard); + if (isSelf()) + { + if (gAgentAvatarp->isUsingBakedTextures()) + { + requestLayerSetUpdate(type); + } + else + { + LLVisualParamHint::requestHintUpdates(); + } + } + } + else + { + tex->setLoadedCallback(onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), type), NULL); + } + } + tex->setMinDiscardLevel(desired_discard); + } + } + local_tex_obj->setImage(tex); + local_tex_obj->setID(tex->getID()); + setBakedReady(type,baked_version_ready,index); +} +//virtual +void LLVOAvatarSelf::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) +{ + if (!isIndexLocalTexture(type)) return; + LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index); + if (local_tex_obj) + { + local_tex_obj->setBakedReady( baked_version_exists ); + } +} + + +// virtual +void LLVOAvatarSelf::dumpLocalTextures() const +{ + llinfos << "Local Textures:" << llendl; + + /* ETextureIndex baked_equiv[] = { + TEX_UPPER_BAKED, + if (isTextureDefined(baked_equiv[i])) */ + for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + ++iter) + { + const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) + continue; + + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + const ETextureIndex baked_equiv = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex; + + const std::string &name = texture_dict->mName; + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(iter->first, 0); + // index is baked texture - index is not relevant. putting in 0 as placeholder + if (isTextureDefined(baked_equiv, 0)) + { +#if LL_RELEASE_FOR_DOWNLOAD + // End users don't get to trivially see avatar texture IDs, makes textures + // easier to steal. JC + llinfos << "LocTex " << name << ": Baked " << llendl; +#else + llinfos << "LocTex " << name << ": Baked " << getTEImage(baked_equiv)->getID() << llendl; +#endif + } + else if (local_tex_obj && local_tex_obj->getImage() != NULL) + { + if (local_tex_obj->getImage()->getID() == IMG_DEFAULT_AVATAR) + { + llinfos << "LocTex " << name << ": None" << llendl; + } + else + { + const LLViewerFetchedTexture* image = local_tex_obj->getImage(); + + llinfos << "LocTex " << name << ": " + << "Discard " << image->getDiscardLevel() << ", " + << "(" << image->getWidth() << ", " << image->getHeight() << ") " +#if !LL_RELEASE_FOR_DOWNLOAD + // End users don't get to trivially see avatar texture IDs, + // makes textures easier to steal + << image->getID() << " " +#endif + << "Priority: " << image->getDecodePriority() + << llendl; + } + } + else + { + llinfos << "LocTex " << name << ": No LLViewerTexture" << llendl; + } + } +} + +//----------------------------------------------------------------------------- +// static +// onLocalTextureLoaded() +//----------------------------------------------------------------------------- + +void LLVOAvatarSelf::onLocalTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src_raw, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) +{ + LLAvatarTexData *data = (LLAvatarTexData *)userdata; + LLVOAvatarSelf *self = (LLVOAvatarSelf *)gObjectList.findObject(data->mAvatarID); + if (self) + { + // We should only be handling local textures for ourself + self->localTextureLoaded(success, src_vi, src_raw, aux_src, discard_level, final, userdata); + } + // ensure data is cleaned up + if (final || !success) + { + delete data; + } +} + +/*virtual*/ void LLVOAvatarSelf::setImage(const U8 te, LLViewerTexture *imagep, const U32 index) +{ + if (isIndexLocalTexture((ETextureIndex)te)) + { + setLocalTexture((ETextureIndex)te, imagep, FALSE ,index); + } + else + { + setTEImage(te,imagep); + } +} + +/*virtual*/ LLViewerTexture* LLVOAvatarSelf::getImage(const U8 te, const U32 index) const +{ + if (isIndexLocalTexture((ETextureIndex)te)) + { + return getLocalTextureGL((ETextureIndex)te,index); + } + else + { + return getTEImage(te); + } +} + + +// static +void LLVOAvatarSelf::dumpTotalLocalTextureByteCount() +{ + S32 gl_bytes = 0; + gAgentAvatarp->getLocalTextureByteCount(&gl_bytes); + llinfos << "Total Avatar LocTex GL:" << (gl_bytes/1024) << "KB" << llendl; +} + +BOOL LLVOAvatarSelf::getIsCloud() const +{ + // do we have our body parts? + if (gAgentWearables.getWearableCount(LLWearableType::WT_SHAPE) == 0 || + gAgentWearables.getWearableCount(LLWearableType::WT_HAIR) == 0 || + gAgentWearables.getWearableCount(LLWearableType::WT_EYES) == 0 || + gAgentWearables.getWearableCount(LLWearableType::WT_SKIN) == 0) + { + lldebugs << "No body parts" << llendl; + return TRUE; + } + + if (!isTextureDefined(TEX_HAIR, 0)) + { + lldebugs << "No hair texture" << llendl; + return TRUE; + } + + if (!mPreviousFullyLoaded) + { + if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_LOWER].mTexLayerSet) && + (!isTextureDefined(TEX_LOWER_BAKED, 0))) + { + lldebugs << "Lower textures not baked" << llendl; + return TRUE; + } + + if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_UPPER].mTexLayerSet) && + (!isTextureDefined(TEX_UPPER_BAKED, 0))) + { + lldebugs << "Upper textures not baked" << llendl; + return TRUE; + } + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + if (i == BAKED_SKIRT && !isWearingWearableType(LLWearableType::WT_SKIRT)) + continue; + + const BakedTextureData& texture_data = mBakedTextureDatas[i]; + if (!isTextureDefined(texture_data.mTextureIndex, 0)) + continue; + + // Check for the case that texture is defined but not sufficiently loaded to display anything. + const LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex, 0 ); + if (!baked_img || !baked_img->hasGLTexture()) + { + lldebugs << "Texture at index " << i << " (texture index is " << texture_data.mTextureIndex << ") is not loaded" << llendl; + return TRUE; + } + } + + lldebugs << "Avatar de-clouded" << llendl; + } + return FALSE; +} + +/*static*/ +void LLVOAvatarSelf::debugOnTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) +{ + gAgentAvatarp->debugTimingLocalTexLoaded(success, src_vi, src, aux_src, discard_level, final, userdata); +} + +void LLVOAvatarSelf::debugTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) +{ + LLAvatarTexData *data = (LLAvatarTexData *)userdata; + if (!data) + { + return; + } + + ETextureIndex index = data->mIndex; + + if (index < 0 || index >= TEX_NUM_INDICES) + { + return; + } + + if (discard_level >=0 && discard_level <= MAX_DISCARD_LEVEL) // ignore discard level -1, as it means we have no data. + { + mDebugTextureLoadTimes[(U32)index][(U32)discard_level] = mDebugSelfLoadTimer.getElapsedTimeF32(); + } + if (final) + { + delete data; + } +} + +void LLVOAvatarSelf::debugBakedTextureUpload(EBakedTextureIndex index, BOOL finished) +{ + U32 done = 0; + if (finished) + { + done = 1; + } + mDebugBakedTextureTimes[index][done] = mDebugSelfLoadTimer.getElapsedTimeF32(); +} + +const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLTexLayerSet* layerset) const +{ + std::string text=""; + + text = llformat("[Final:%d Avail:%d] ",isLocalTextureDataFinal(layerset), isLocalTextureDataAvailable(layerset)); + + /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) + return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ + for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const EBakedTextureIndex baked_index = baked_iter->first; + if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) + { + const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; + text += llformat("%d-%s ( ",baked_index, baked_dict->mName.c_str()); + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + if (wearable_count > 0) + { + text += LLWearableType::getTypeName(wearable_type) + ":"; + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + const U32 discard_level = getLocalDiscardLevel(tex_index, wearable_index); + std::string discard_str = llformat("%d ",discard_level); + text += llformat("%d ",discard_level); + } + } + } + text += ")"; + break; + } + } + return text; +} + +const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const +{ + std::string text; + const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + BOOL is_texture_final = TRUE; + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + is_texture_final &= (getLocalDiscardLevel(*local_tex_iter, wearable_index) <= (S32)(override_tex_discard_level)); + } + } + text += llformat("%s:%d ",baked_dict->mName.c_str(),is_texture_final); + } + return text; +} + +const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) const +{ + if (canGrabBakedTexture(baked_index)) + { + ETextureIndex tex_index = LLVOAvatarDictionary::bakedToLocalTextureIndex(baked_index); + if (tex_index == TEX_NUM_INDICES) + { + return LLUUID::null; + } + return getTEImage( tex_index )->getID(); + } + return LLUUID::null; +} + +BOOL LLVOAvatarSelf::canGrabBakedTexture(EBakedTextureIndex baked_index) const +{ + ETextureIndex tex_index = LLVOAvatarDictionary::bakedToLocalTextureIndex(baked_index); + if (tex_index == TEX_NUM_INDICES) + { + return FALSE; + } + // Check if the texture hasn't been baked yet. + if (!isTextureDefined(tex_index, 0)) + { + lldebugs << "getTEImage( " << (U32) tex_index << " )->getID() == IMG_DEFAULT_AVATAR" << llendl; + return FALSE; + } + + if (gAgent.isGodlikeWithoutAdminMenuFakery()) + return TRUE; + + // Check permissions of textures that show up in the + // baked texture. We don't want people copying people's + // work via baked textures. + + const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index); + for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin(); + iter != baked_dict->mLocalTextures.end(); + ++iter) + { + const ETextureIndex t_index = (*iter); + LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(t_index); + U32 count = gAgentWearables.getWearableCount(wearable_type); + lldebugs << "Checking index " << (U32) t_index << " count: " << count << llendl; + + for (U32 wearable_index = 0; wearable_index < count; ++wearable_index) + { + LLWearable *wearable = gAgentWearables.getWearable(wearable_type, wearable_index); + if (wearable) + { + const LLLocalTextureObject *texture = wearable->getLocalTextureObject((S32)t_index); + const LLUUID& texture_id = texture->getID(); + if (texture_id != IMG_DEFAULT_AVATAR) + { + // Search inventory for this texture. + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLAssetIDMatches asset_id_matches(texture_id); + gInventory.collectDescendentsIf(LLUUID::null, + cats, + items, + LLInventoryModel::INCLUDE_TRASH, + asset_id_matches); + + BOOL can_grab = FALSE; + lldebugs << "item count for asset " << texture_id << ": " << items.count() << llendl; + if (items.count()) + { + // search for full permissions version + for (S32 i = 0; i < items.count(); i++) + { + LLViewerInventoryItem* itemp = items[i]; + if (itemp->getIsFullPerm()) + { + can_grab = TRUE; + break; + } + } + } + if (!can_grab) return FALSE; + } + } + } + } + + return TRUE; +} + +void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTexture* imagep, + F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked, U32 index ) +{ + if (!isIndexLocalTexture(type)) return; + + if (!covered_by_baked) + { + if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR && imagep->getDiscardLevel() != 0) + { + F32 desired_pixels; + desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); + imagep->setBoostLevel(getAvatarBoostLevel()); + + imagep->resetTextureStats(); + imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); + imagep->addTextureStats( desired_pixels / texel_area_ratio ); + imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; + imagep->forceUpdateBindStats() ; + if (imagep->getDiscardLevel() < 0) + { + mHasGrey = TRUE; // for statistics gathering + } + } + else + { + // texture asset is missing + mHasGrey = TRUE; // for statistics gathering + } + } +} + +LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 wearable_index) const +{ + LLWearableType::EType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i); + LLWearable* wearable = gAgentWearables.getWearable(type, wearable_index); + if (wearable) + { + return wearable->getLocalTextureObject(i); + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// getBakedTE() +// Used by the LayerSet. (Layer sets don't in general know what textures depend on them.) +//----------------------------------------------------------------------------- +ETextureIndex LLVOAvatarSelf::getBakedTE( const LLTexLayerSet* layerset ) const +{ + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + if (layerset == mBakedTextureDatas[i].mTexLayerSet ) + { + return mBakedTextureDatas[i].mTextureIndex; + } + } + llassert(0); + return TEX_HEAD_BAKED; +} + + +void LLVOAvatarSelf::setNewBakedTexture(LLVOAvatarDefines::EBakedTextureIndex i, const LLUUID &uuid) +{ + ETextureIndex index = LLVOAvatarDictionary::bakedToLocalTextureIndex(i); + setNewBakedTexture(index, uuid); +} + + +//----------------------------------------------------------------------------- +// setNewBakedTexture() +// A new baked texture has been successfully uploaded and we can start using it now. +//----------------------------------------------------------------------------- +void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) +{ + // Baked textures live on other sims. + LLHost target_host = getObjectHost(); + setTEImage( te, LLViewerTextureManager::getFetchedTextureFromHost( uuid, target_host ) ); + updateMeshTextures(); + dirtyMesh(); + + LLVOAvatar::cullAvatarsByPixelArea(); + + /* switch(te) + case TEX_HEAD_BAKED: + llinfos << "New baked texture: HEAD" << llendl; */ + const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(te); + if (texture_dict->mIsBakedTexture) + { + debugBakedTextureUpload(texture_dict->mBakedTextureIndex, TRUE); // FALSE for start of upload, TRUE for finish. + llinfos << "New baked texture: " << texture_dict->mName << " UUID: " << uuid <getBakedTextures().begin(); + baked_iter != LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const LLVOAvatarDefines::EBakedTextureIndex baked_index = baked_iter->first; + const LLTexLayerSet *layerset = debugGetLayerSet(baked_index); + if (!layerset) continue; + const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); + if (!layerset_buffer) continue; + llinfos << layerset_buffer->dumpTextureInfo() << llendl; + } +} + +void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const +{ + LL_DEBUGS("Avatar Rez") + << llformat("%s. Time from avatar creation: %.2f", msg.c_str(), mDebugSelfLoadTimer.getElapsedTimeF32()) + << llendl; +} + +void LLVOAvatarSelf::reportAvatarRezTime() const +{ + // TODO: report mDebugSelfLoadTimer.getElapsedTimeF32() somehow. +} + +//----------------------------------------------------------------------------- +// setCachedBakedTexture() +// A baked texture id was received from a cache query, make it active +//----------------------------------------------------------------------------- +void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid ) +{ + setTETexture( te, uuid ); + + /* switch(te) + case TEX_HEAD_BAKED: + if( mHeadLayerSet ) + mHeadLayerSet->cancelUpload(); */ + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + if ( mBakedTextureDatas[i].mTextureIndex == te && mBakedTextureDatas[i].mTexLayerSet) + { + if (mInitialBakeIDs[i] != LLUUID::null) + { + if (mInitialBakeIDs[i] == uuid) + { + llinfos << "baked texture correctly loaded at login! " << i << llendl; + } + else + { + llwarns << "baked texture does not match id loaded at login!" << i << llendl; + } + mInitialBakeIDs[i] = LLUUID::null; + } + mBakedTextureDatas[i].mTexLayerSet->cancelUpload(); + } + } +} + +// static +void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**) +{ + LLUUID texture_id; + msg->getUUID("TextureData", "TextureID", texture_id); + if (!isAgentAvatarValid()) return; + + // If this is a texture corresponding to one of our baked entries, + // just rebake that layer set. + BOOL found = FALSE; + + /* ETextureIndex baked_texture_indices[BAKED_NUM_INDICES] = + TEX_HEAD_BAKED, + TEX_UPPER_BAKED, */ + for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + ++iter) + { + const ETextureIndex index = iter->first; + const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + if (texture_dict->mIsBakedTexture) + { + if (texture_id == gAgentAvatarp->getTEImage(index)->getID()) + { + LLTexLayerSet* layer_set = gAgentAvatarp->getLayerSet(index); + if (layer_set) + { + llinfos << "TAT: rebake - matched entry " << (S32)index << llendl; + gAgentAvatarp->invalidateComposite(layer_set, TRUE); + found = TRUE; + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES); + } + } + } + } + + // If texture not found, rebake all entries. + if (!found) + { + gAgentAvatarp->forceBakeAllTextures(); + } + else + { + // Not sure if this is necessary, but forceBakeAllTextures() does it. + gAgentAvatarp->updateMeshTextures(); + } +} + +BOOL LLVOAvatarSelf::isUsingBakedTextures() const +{ + // Composite textures are used during appearance mode. + if (gAgentCamera.cameraCustomizeAvatar()) + return FALSE; + + return TRUE; +} + + +void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug) +{ + llinfos << "TAT: forced full rebake. " << llendl; + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + ETextureIndex baked_index = mBakedTextureDatas[i].mTextureIndex; + LLTexLayerSet* layer_set = getLayerSet(baked_index); + if (layer_set) + { + if (slam_for_debug) + { + layer_set->setUpdatesEnabled(TRUE); + layer_set->cancelUpload(); + } + + invalidateComposite(layer_set, TRUE); + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES); + } + else + { + llwarns << "TAT: NO LAYER SET FOR " << (S32)baked_index << llendl; + } + } + + // Don't know if this is needed + updateMeshTextures(); +} + +//----------------------------------------------------------------------------- +// requestLayerSetUpdate() +//----------------------------------------------------------------------------- +void LLVOAvatarSelf::requestLayerSetUpdate(ETextureIndex index ) +{ + /* switch(index) + case LOCTEX_UPPER_BODYPAINT: + case LOCTEX_UPPER_SHIRT: + if( mUpperBodyLayerSet ) + mUpperBodyLayerSet->requestUpdate(); */ + const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) + return; + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + if (mBakedTextureDatas[baked_index].mTexLayerSet) + { + mBakedTextureDatas[baked_index].mTexLayerSet->requestUpdate(); + } +} + +LLTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const +{ + /* switch(index) + case TEX_HEAD_BAKED: + case TEX_HEAD_BODYPAINT: + return mHeadLayerSet; */ + const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + if (texture_dict->mIsUsedByBakedTexture) + { + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + return mBakedTextureDatas[baked_index].mTexLayerSet; + } + return NULL; +} + +LLTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) const +{ + /* switch(index) + case TEX_HEAD_BAKED: + case TEX_HEAD_BODYPAINT: + return mHeadLayerSet; */ + if (baked_index >= 0 && baked_index < BAKED_NUM_INDICES) + { + return mBakedTextureDatas[baked_index].mTexLayerSet; + } + return NULL; +} + + +// static +void LLVOAvatarSelf::onCustomizeStart() +{ + // We're no longer doing any baking or invalidating on entering + // appearance editing mode. Leaving function in place in case + // further changes require us to do something at this point - Nyx +} + +// static +void LLVOAvatarSelf::onCustomizeEnd() +{ + if (isAgentAvatarValid()) + { + gAgentAvatarp->invalidateAll(); + } +} + +// HACK: this will null out the avatar's local texture IDs before the TE message is sent +// to ensure local texture IDs are not sent to other clients in the area. +// this is a short-term solution. The long term solution will be to not set the texture +// IDs in the avatar object, and keep them only in the wearable. +// This will involve further refactoring that is too risky for the initial release of 2.0. +bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const +{ + LLUUID texture_id[TEX_NUM_INDICES]; + // pack away current TEs to make sure we don't send them out + for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + ++iter) + { + const ETextureIndex index = iter->first; + const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + if (!texture_dict->mIsBakedTexture) + { + LLTextureEntry* entry = getTE((U8) index); + texture_id[index] = entry->getID(); + if (SHClientTagMgr::instance().getIsEnabled() && index == 0 && gSavedSettings.getBOOL("AscentUseTag")) + entry->setID(LLUUID(gSavedSettings.getString("AscentReportClientUUID"))); + else + entry->setID(IMG_DEFAULT_AVATAR); + } + } + + bool success = packTEMessage(mesgsys); + + // unpack TEs to make sure we don't re-trigger a bake + for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + ++iter) + { + const ETextureIndex index = iter->first; + const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + if (!texture_dict->mIsBakedTexture) + { + LLTextureEntry* entry = getTE((U8) index); + entry->setID(texture_id[index]); + } + } + + return success; +} + //------------------------------------------------------------------------ // needsRenderBeam() //------------------------------------------------------------------------ @@ -671,4 +2644,104 @@ BOOL LLVOAvatarSelf::needsRenderBeam() is_touching_or_grabbing = FALSE; } return is_touching_or_grabbing || (mState & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection()); +} + +// static +void LLVOAvatarSelf::deleteScratchTextures() +{ + if(gAuditTexture) + { + S32 total_tex_size = sScratchTexBytes ; + S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ; + + if( sScratchTexNames.checkData( GL_LUMINANCE ) ) + { + LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= tex_size ; + } + if( sScratchTexNames.checkData( GL_ALPHA ) ) + { + LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= tex_size ; + } + if( sScratchTexNames.checkData( GL_COLOR_INDEX ) ) + { + LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= tex_size ; + } + if( sScratchTexNames.checkData( LLRender::sGLCoreProfile ? GL_RG : GL_LUMINANCE_ALPHA ) ) + { + LLImageGL::decTextureCounter(tex_size, 2, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= 2 * tex_size ; + } + if( sScratchTexNames.checkData( GL_RGB ) ) + { + LLImageGL::decTextureCounter(tex_size, 3, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= 3 * tex_size ; + } + if( sScratchTexNames.checkData( GL_RGBA ) ) + { + LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= 4 * tex_size ; + } + //others + while(total_tex_size > 0) + { + LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= 4 * tex_size ; + } + } + + for( LLGLuint* namep = sScratchTexNames.getFirstData(); + namep; + namep = sScratchTexNames.getNextData() ) + { + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 0, -1, 1, (U32 *)namep ); + stop_glerror(); + } + + if( sScratchTexBytes ) + { + lldebugs << "Clearing Scratch Textures " << (sScratchTexBytes/1024) << "KB" << llendl; + + sScratchTexNames.deleteAllData(); + sScratchTexLastBindTime.deleteAllData(); + LLImageGL::sGlobalTextureMemoryInBytes -= sScratchTexBytes; + sScratchTexBytes = 0; + } +} + +// static +void LLVOAvatarSelf::dumpScratchTextureByteCount() +{ + llinfos << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << llendl; +} + +// static +void LLVOAvatarSelf::onChangeSelfInvisible(bool invisible) +{ + if (isAgentAvatarValid()) + { + gAgentAvatarp->setInvisible(invisible); + } +} + +void LLVOAvatarSelf::setInvisible(bool invisible) +{ + if (invisible) + { + setCompositeUpdatesEnabled(FALSE); + for (U32 i = 0; i < mBakedTextureDatas.size(); i++ ) + { + setNewBakedTexture(mBakedTextureDatas[i].mTextureIndex, IMG_INVISIBLE); + } + gAgent.sendAgentSetAppearance(); + } + else + { + setCompositeUpdatesEnabled(TRUE); + invalidateAll(); + requestLayerSetUploads(); + gAgent.sendAgentSetAppearance(); + } } \ No newline at end of file diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index d8e1187cb..0105315ff 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -31,6 +31,8 @@ #include "llviewertexture.h" #include "llvoavatar.h" +struct LocalTextureData; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatarSelf @@ -57,6 +59,7 @@ protected: BOOL loadAvatarSelf(); BOOL buildSkeletonSelf(const LLVOAvatarSkeletonInfo *info); BOOL buildMenus(); + /*virtual*/ BOOL loadLayersets(); /** Initialization ** ** @@ -84,12 +87,33 @@ public: void resetJointPositions( void ); + /*virtual*/ BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE ); + /*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE ); + /*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE ); + /*virtual*/ void updateVisualParams(); + /*virtual*/ void idleUpdateAppearanceAnimation(); + + /*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys, + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp); + +private: + // helper function. Passed in param is assumed to be in avatar's parameter list. + BOOL setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE ); + /** Initialization ** ** *******************************************************************************/ +private: + LLUUID mInitialBakeIDs[6]; + bool mInitialBakesLoaded; + + /******************************************************************************** ** ** ** STATE @@ -105,7 +129,16 @@ public: /*virtual*/ BOOL updateCharacter(LLAgent &agent); /*virtual*/ void idleUpdateTractorBeam(); + //-------------------------------------------------------------------- + // Loading state + //-------------------------------------------------------------------- +public: + /*virtual*/ BOOL getIsCloud() const; + //-------------------------------------------------------------------- + // Region state + //-------------------------------------------------------------------- + void resetRegionCrossingTimer() { mRegionCrossingTimer.reset(); } private: U64 mLastRegionHandle; @@ -130,12 +163,115 @@ private: LLPointer mBeam; LLFrameTimer mBeamTimer; + //-------------------------------------------------------------------- + // LLVOAvatar Constants + //-------------------------------------------------------------------- +public: + /*virtual*/ LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_SELF; } + /*virtual*/ LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_BAKED_SELF; } + /*virtual*/ S32 getTexImageSize() const { return LLVOAvatar::getTexImageSize()*4; } /** Rendering ** ** *******************************************************************************/ + +/******************************************************************************** + ** ** + ** TEXTURES + **/ + + //-------------------------------------------------------------------- + // Loading status + //-------------------------------------------------------------------- +public: + /*virtual*/ bool hasPendingBakedUploads() const; + S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex type, U32 index) const; + bool areTexturesCurrent() const; + BOOL isLocalTextureDataAvailable(const LLTexLayerSet* layerset) const; + BOOL isLocalTextureDataFinal(const LLTexLayerSet* layerset) const; + BOOL isBakedTextureFinal(const LLVOAvatarDefines::EBakedTextureIndex index) const; + // If you want to check all textures of a given type, pass gAgentWearables.getWearableCount() for index + /*virtual*/ BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const; + /*virtual*/ BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; + /*virtual*/ BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const; + + + //-------------------------------------------------------------------- + // Local Textures + //-------------------------------------------------------------------- +public: + BOOL getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture** image_gl_pp, U32 index) const; + LLViewerFetchedTexture* getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, U32 index) const; + const LLUUID& getLocalTextureID(LLVOAvatarDefines::ETextureIndex type, U32 index) const; + void setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index); + /*virtual*/ void setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index); +protected: + /*virtual*/ void setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index); + void localTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); + void getLocalTextureByteCount(S32* gl_byte_count) const; + /*virtual*/ void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index); + LLLocalTextureObject* getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 index) const; + +private: + static void onLocalTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); + + /*virtual*/ void setImage(const U8 te, LLViewerTexture *imagep, const U32 index); + /*virtual*/ LLViewerTexture* getImage(const U8 te, const U32 index) const; + + + //-------------------------------------------------------------------- + // Baked textures + //-------------------------------------------------------------------- +public: + LLVOAvatarDefines::ETextureIndex getBakedTE(const LLTexLayerSet* layerset ) const; + void setNewBakedTexture(LLVOAvatarDefines::EBakedTextureIndex i, const LLUUID &uuid); + void setNewBakedTexture(LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid); + void setCachedBakedTexture(LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid); + void forceBakeAllTextures(bool slam_for_debug = false); + static void processRebakeAvatarTextures(LLMessageSystem* msg, void**); + BOOL isUsingBakedTextures() const; // e.g. false if in appearance edit mode protected: /*virtual*/ void removeMissingBakedTextures(); + + //-------------------------------------------------------------------- + // Layers + //-------------------------------------------------------------------- +public: + void requestLayerSetUploads(); + void requestLayerSetUpload(LLVOAvatarDefines::EBakedTextureIndex i); + void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i); + LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const; + LLTexLayerSet* getLayerSet(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; + + //-------------------------------------------------------------------- + // Composites + //-------------------------------------------------------------------- +public: + /* virtual */ void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result); + /* virtual */ void invalidateAll(); + /* virtual */ void setCompositeUpdatesEnabled(bool b); // only works for self + /* virtual */ void setCompositeUpdatesEnabled(U32 index, bool b); + /* virtual */ bool isCompositeUpdateEnabled(U32 index); + void setupComposites(); + void updateComposites(); + + const LLUUID& grabBakedTexture(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; + BOOL canGrabBakedTexture(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; + + + //-------------------------------------------------------------------- + // Scratch textures (used for compositing) + //-------------------------------------------------------------------- +public: + static void deleteScratchTextures(); +private: + static S32 sScratchTexBytes; + static LLMap< LLGLenum, LLGLuint*> sScratchTexNames; + static LLMap< LLGLenum, F32*> sScratchTexLastBindTime; + +/** Textures + ** ** + *******************************************************************************/ /******************************************************************************** ** ** ** MESHES @@ -147,6 +283,39 @@ protected: ** ** *******************************************************************************/ +/******************************************************************************** + ** ** + ** WEARABLES + **/ + +public: + /*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type) const; + void wearableUpdated(LLWearableType::EType type, BOOL upload_result); +protected: + U32 getNumWearables(LLVOAvatarDefines::ETextureIndex i) const; + + //-------------------------------------------------------------------- + // Attachments + //-------------------------------------------------------------------- +public: + void updateAttachmentVisibility(U32 camera_mode); + BOOL isWearingAttachment(const LLUUID& inv_item_id) const; + BOOL attachmentWasRequested(const LLUUID& inv_item_id) const; + void addAttachmentRequest(const LLUUID& inv_item_id); + void removeAttachmentRequest(const LLUUID& inv_item_id); + LLViewerObject* getWornAttachment(const LLUUID& inv_item_id); +// [RLVa:KB] - Checked: 2009-12-18 (RLVa-1.1.0i) | Added: RLVa-1.1.0i + LLViewerJointAttachment* getWornAttachmentPoint(const LLUUID& inv_item_id) const; +// [/RLVa:KB] + const std::string getAttachedPointName(const LLUUID& inv_item_id) const; + /*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object); + /*virtual*/ BOOL detachObject(LLViewerObject *viewer_object); + static BOOL detachAttachmentIntoInventory(const LLUUID& item_id); + +private: + // Track attachments that have been requested but have not arrived yet. + mutable std::map mAttachmentRequests; + //-------------------------------------------------------------------- // HUDs //-------------------------------------------------------------------- @@ -156,9 +325,83 @@ private: /** Attachments ** ** *******************************************************************************/ + +/******************************************************************************** + ** ** + ** APPEARANCE + **/ + +public: + static void onCustomizeStart(); + static void onCustomizeEnd(); + + //-------------------------------------------------------------------- + // Visibility + //-------------------------------------------------------------------- +public: + bool sendAppearanceMessage(LLMessageSystem *mesgsys) const; + +/** Appearance + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** DIAGNOSTICS + **/ + + //-------------------------------------------------------------------- + // General + //-------------------------------------------------------------------- +public: + static void dumpTotalLocalTextureByteCount(); + void dumpLocalTextures() const; + static void dumpScratchTextureByteCount(); + + //-------------------------------------------------------------------- + // Avatar Rez Metrics + //-------------------------------------------------------------------- +public: + struct LLAvatarTexData + { + LLAvatarTexData(const LLUUID& id, LLVOAvatarDefines::ETextureIndex index) : + mAvatarID(id), + mIndex(index) + {} + LLUUID mAvatarID; + LLVOAvatarDefines::ETextureIndex mIndex; + }; + void debugWearablesLoaded() { mDebugTimeWearablesLoaded = mDebugSelfLoadTimer.getElapsedTimeF32(); } + void debugAvatarVisible() { mDebugTimeAvatarVisible = mDebugSelfLoadTimer.getElapsedTimeF32(); } + void outputRezDiagnostics() const; + void outputRezTiming(const std::string& msg) const; + void reportAvatarRezTime() const; + void debugBakedTextureUpload(LLVOAvatarDefines::EBakedTextureIndex index, BOOL finished); + static void debugOnTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); + + BOOL isAllLocalTextureDataFinal() const; + + const LLTexLayerSet* debugGetLayerSet(LLVOAvatarDefines::EBakedTextureIndex index) const { return mBakedTextureDatas[index].mTexLayerSet; } + const std::string debugDumpLocalTextureDataInfo(const LLTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer + const std::string debugDumpAllLocalTextureDataInfo() const; // Lists out which baked textures are at highest LOD +private: + LLFrameTimer mDebugSelfLoadTimer; + F32 mDebugTimeWearablesLoaded; + F32 mDebugTimeAvatarVisible; + F32 mDebugTextureLoadTimes[LLVOAvatarDefines::TEX_NUM_INDICES][MAX_DISCARD_LEVEL+1]; // load time for each texture at each discard level + F32 mDebugBakedTextureTimes[LLVOAvatarDefines::BAKED_NUM_INDICES][2]; // time to start upload and finish upload of each baked texture + void debugTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); + +/** Diagnostics + ** ** + *******************************************************************************/ + +public: + static void onChangeSelfInvisible(bool invisible); + void setInvisible(bool invisible); }; -extern LLVOAvatarSelf *gAgentAvatarp; +extern LLPointer gAgentAvatarp; BOOL isAgentAvatarValid(); diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp index 18e597b15..b63103acb 100644 --- a/indra/newview/llvoclouds.cpp +++ b/indra/newview/llvoclouds.cpp @@ -52,6 +52,7 @@ #include "pipeline.h" #include "llspatialpartition.h" +#if ENABLE_CLASSIC_CLOUDS LLUUID gCloudTextureID = IMG_CLOUD_POOF; @@ -119,29 +120,48 @@ static LLFastTimer::DeclareTimer FTM_UPDATE_CLOUDS("Cloud Update"); BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) { LLFastTimer ftm(FTM_UPDATE_CLOUDS); - if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS))) - { - return TRUE; - } - if (drawable->isVisible()) + dirtySpatialGroup(); + + S32 num_parts = mCloudGroupp->getNumPuffs(); + LLFace *facep; + LLSpatialGroup* group = drawable->getSpatialGroup(); + if (!group && num_parts) + { + drawable->movePartition(); + group = drawable->getSpatialGroup(); + } + + if (group && group->isVisible()) { dirtySpatialGroup(TRUE); } - LLFace *facep; - - S32 num_faces = mCloudGroupp->getNumPuffs(); - - if (num_faces > drawable->getNumFaces()) + if (!num_parts) { - drawable->setNumFacesFast(num_faces, NULL, getTEImage(0)); + if (group && drawable->getNumFaces()) + { + group->setState(LLSpatialGroup::GEOM_DIRTY); + } + drawable->setNumFaces(0, NULL, getTEImage(0)); + LLPipeline::sCompiles++; + return TRUE; + } + + if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS))) + { + return TRUE; + } + + if (num_parts > drawable->getNumFaces()) + { + drawable->setNumFacesFast(num_parts+num_parts/4, NULL, getTEImage(0)); } mDepth = (getPositionAgent()-LLViewerCamera::getInstance()->getOrigin())*LLViewerCamera::getInstance()->getAtAxis(); S32 face_indx = 0; - for ( ; face_indx < num_faces; face_indx++) + for ( ; face_indx < num_parts; face_indx++) { facep = drawable->getFace(face_indx); if (!facep) @@ -150,16 +170,18 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) continue; } + facep->setTEOffset(face_indx); facep->setSize(4, 6); - facep->setTEOffset(face_indx); - facep->setTexture(getTEImage(0)); + facep->setViewerObject(this); + const LLCloudPuff &puff = mCloudGroupp->getPuff(face_indx); const LLVector3 puff_pos_agent = gAgent.getPosAgentFromGlobal(puff.getPositionGlobal()); facep->mCenterLocal = puff_pos_agent; /// Update cloud color based on sun color. LLColor4 float_color(LLColor3(gSky.getSunDiffuseColor() + gSky.getSunAmbientColor()),puff.getAlpha()); facep->setFaceColor(float_color); + facep->setTexture(getTEImage(0)); } for ( ; face_indx < drawable->getNumFaces(); face_indx++) { @@ -174,8 +196,8 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) facep->setSize(0,0); } - drawable->movePartition(); - + mDrawable->movePartition(); + LLPipeline::sCompiles++; return TRUE; } @@ -212,8 +234,6 @@ void LLVOClouds::getGeometry(S32 idx, color.setVec(float_color); facep->setFaceColor(float_color); - U32 vert_offset = facep->getGeomIndex(); - LLVector4a part_pos_agent; part_pos_agent.load3(facep->mCenterLocal.mV); LLVector4a at; @@ -250,33 +270,15 @@ void LLVOClouds::getGeometry(S32 idx, verticesp->setAdd(ppamu, right); (*verticesp++).getF32ptr()[3] = 0.f; - // *verticesp++ = puff_pos_agent - right + up; - // *verticesp++ = puff_pos_agent - right - up; - // *verticesp++ = puff_pos_agent + right + up; - // *verticesp++ = puff_pos_agent + right - up; - *colorsp++ = color; *colorsp++ = color; *colorsp++ = color; *colorsp++ = color; - *texcoordsp++ = LLVector2(0.f, 1.f); - *texcoordsp++ = LLVector2(0.f, 0.f); - *texcoordsp++ = LLVector2(1.f, 1.f); - *texcoordsp++ = LLVector2(1.f, 0.f); - *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; - - *indicesp++ = vert_offset + 0; - *indicesp++ = vert_offset + 1; - *indicesp++ = vert_offset + 2; - - *indicesp++ = vert_offset + 1; - *indicesp++ = vert_offset + 3; - *indicesp++ = vert_offset + 2; } U32 LLVOClouds::getPartitionType() const @@ -302,3 +304,4 @@ LLCloudPartition::LLCloudPartition() mPartitionType = LLViewerRegion::PARTITION_CLOUD; } +#endif diff --git a/indra/newview/llvoclouds.h b/indra/newview/llvoclouds.h index dfe664beb..685400f32 100644 --- a/indra/newview/llvoclouds.h +++ b/indra/newview/llvoclouds.h @@ -42,7 +42,7 @@ class LLViewerCloudGroup; class LLCloudGroup; - +#if ENABLE_CLASSIC_CLOUDS class LLVOClouds : public LLAlphaObject { public: @@ -82,4 +82,5 @@ protected: extern LLUUID gCloudTextureID; +#endif #endif // LL_VO_CLOUDS_H diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 1fa3fcac6..5a58ae770 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -41,6 +41,7 @@ #include "llnotificationsutil.h" #include "llviewerwindow.h" #include "lldrawable.h" +#include "lldrawpoolalpha.h" #include "llface.h" #include "llsky.h" #include "llsurface.h" @@ -403,8 +404,10 @@ BOOL LLVOGrass::updateLOD() { mNumBlades <<= 1; } - - face->setSize(mNumBlades*8, mNumBlades*12); + if (face) + { + face->setSize(mNumBlades*8, mNumBlades*12); + } gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } else if (num_blades <= (mNumBlades >> 1)) @@ -414,7 +417,10 @@ BOOL LLVOGrass::updateLOD() mNumBlades >>=1; } - face->setSize(mNumBlades*8, mNumBlades*12); + if (face) + { + face->setSize(mNumBlades*8, mNumBlades*12); + } gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); return TRUE; } @@ -472,14 +478,16 @@ void LLVOGrass::plantBlades() } LLFace *face = mDrawable->getFace(0); + if (face) + { + face->setTexture(getTEImage(0)); + face->setState(LLFace::GLOBAL); + face->setSize(mNumBlades * 8, mNumBlades * 12); + face->setVertexBuffer(NULL); + face->setTEOffset(0); + face->mCenterLocal = mPosition + mRegionp->getOriginAgent(); + } - face->setTexture(getTEImage(0)); - face->setState(LLFace::GLOBAL); - face->setSize(mNumBlades * 8, mNumBlades * 12); - face->setVertexBuffer(NULL); - face->setTEOffset(0); - face->mCenterLocal = mPosition + mRegionp->getOriginAgent(); - mDepth = (face->mCenterLocal - LLViewerCamera::getInstance()->getOrigin())*LLViewerCamera::getInstance()->getAtAxis(); mDrawable->setPosition(face->mCenterLocal); mDrawable->movePartition(); @@ -509,6 +517,8 @@ void LLVOGrass::getGeometry(S32 idx, LLColor4U color(255,255,255,255); LLFace *face = mDrawable->getFace(idx); + if (!face) + return; F32 width = sSpeciesTable[mSpecies]->mBladeSizeX; F32 height = sSpeciesTable[mSpecies]->mBladeSizeY; @@ -617,6 +627,7 @@ U32 LLVOGrass::getPartitionType() const } LLGrassPartition::LLGrassPartition() +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB) { mDrawableType = LLPipeline::RENDER_TYPE_GRASS; mPartitionType = LLViewerRegion::PARTITION_GRASS; @@ -627,6 +638,143 @@ LLGrassPartition::LLGrassPartition() mBufferUsage = GL_DYNAMIC_DRAW_ARB; } +void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count) +{ + group->mBufferUsage = mBufferUsage; + + mFaceList.clear(); + + LLViewerCamera* camera = LLViewerCamera::getInstance(); + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + { + LLDrawable* drawablep = *i; + + if (drawablep->isDead()) + { + continue; + } + + LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get(); + obj->mDepth = 0.f; + + if (drawablep->isAnimating()) + { + group->mBufferUsage = GL_STREAM_DRAW_ARB; + } + + U32 count = 0; + for (S32 j = 0; j < drawablep->getNumFaces(); ++j) + { + drawablep->updateFaceSize(j); + + LLFace* facep = drawablep->getFace(j); + if ( !facep || !facep->hasGeometry()) + { + continue; + } + + if ((facep->getGeomCount() + vertex_count) <= 65536) + { + count++; + facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis(); + obj->mDepth += facep->mDistance; + + mFaceList.push_back(facep); + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + llassert(facep->getIndicesCount() < 65536); + } + else + { + facep->clearVertexBuffer(); + } + } + + obj->mDepth /= count; + } +} + +static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB"); + +void LLGrassPartition::getGeometry(LLSpatialGroup* group) +{ + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + LLFastTimer ftm(FTM_REBUILD_GRASS_VB); + + std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); + + U32 index_count = 0; + U32 vertex_count = 0; + + group->clearDrawMap(); + + LLVertexBuffer* buffer = group->mVertexBuffer; + + LLStrider indicesp; + LLStrider verticesp; + LLStrider normalsp; + LLStrider texcoordsp; + LLStrider colorsp; + + buffer->getVertexStrider(verticesp); + buffer->getNormalStrider(normalsp); + buffer->getColorStrider(colorsp); + buffer->getTexCoord0Strider(texcoordsp); + buffer->getIndexStrider(indicesp); + + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; + + for (std::vector::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) + { + LLFace* facep = *i; + LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); + facep->setGeomIndex(vertex_count); + facep->setIndicesIndex(index_count); + facep->setVertexBuffer(buffer); + facep->setPoolType(LLDrawPool::POOL_ALPHA); + object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + S32 idx = draw_vec.size()-1; + + BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + F32 vsize = facep->getVirtualSize(); + + if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + draw_vec[idx]->mTexture == facep->getTexture() && + (U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange && + //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && + draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 && + draw_vec[idx]->mFullbright == fullbright) + { + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } + else + { + U32 start = facep->getGeomIndex(); + U32 end = start + facep->getGeomCount()-1; + U32 offset = facep->getIndicesStart(); + U32 count = facep->getIndicesCount(); + LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), + //facep->getTexture(), + buffer, fullbright); + info->mExtents[0] = group->mObjectExtents[0]; + info->mExtents[1] = group->mObjectExtents[1]; + info->mVSize = vsize; + draw_vec.push_back(info); + //for alpha sorting + facep->setDrawInfo(info); + } + } + + buffer->flush(); + mFaceList.clear(); +} + // virtual void LLVOGrass::updateDrawable(BOOL force_damped) { @@ -713,7 +861,6 @@ BOOL LLVOGrass::lineSegmentIntersect(const LLVector3& start, const LLVector3& en position.mV[2] += blade_height; v[3] = v1 = position + mRegionp->getOriginAgent(); - F32 a,b,t; BOOL hit = FALSE; diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp index ebb7bfda7..3300cb697 100644 --- a/indra/newview/llvoground.cpp +++ b/indra/newview/llvoground.cpp @@ -88,6 +88,7 @@ LLDrawable *LLVOGround::createDrawable(LLPipeline *pipeline) return mDrawable; } +// TO DO - this always returns TRUE, BOOL LLVOGround::updateGeometry(LLDrawable *drawable) { LLStrider verticesp; @@ -102,6 +103,8 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable) if (drawable->getNumFaces() < 1) drawable->addFace(poolp, NULL); face = drawable->getFace(0); + if (!face) + return TRUE; if (!face->getVertexBuffer()) { diff --git a/indra/newview/llvoiceremotectrl.cpp b/indra/newview/llvoiceremotectrl.cpp index 73d8c1087..b496f07a7 100644 --- a/indra/newview/llvoiceremotectrl.cpp +++ b/indra/newview/llvoiceremotectrl.cpp @@ -69,17 +69,15 @@ LLVoiceRemoteCtrl::~LLVoiceRemoteCtrl() BOOL LLVoiceRemoteCtrl::postBuild() { mTalkBtn = getChild("push_to_talk"); - mTalkBtn->setClickedCallback(onBtnTalkClicked); - mTalkBtn->setHeldDownCallback(onBtnTalkHeld); - mTalkBtn->setMouseUpCallback(onBtnTalkReleased); + mTalkBtn->setClickedCallback(boost::bind(&LLVoiceRemoteCtrl::onBtnTalkClicked)); + mTalkBtn->setHeldDownCallback(boost::bind(&LLVoiceRemoteCtrl::onBtnTalkHeld)); + mTalkBtn->setMouseUpCallback(boost::bind(&LLVoiceRemoteCtrl::onBtnTalkReleased)); mTalkLockBtn = getChild("ptt_lock"); - mTalkLockBtn->setClickedCallback(onBtnLock); - mTalkLockBtn->setCallbackUserData(this); + mTalkLockBtn->setClickedCallback(boost::bind(&LLVoiceRemoteCtrl::onBtnLock,this)); mSpeakersBtn = getChild("speakers_btn"); - mSpeakersBtn->setClickedCallback(onClickSpeakers); - mSpeakersBtn->setCallbackUserData(this); + mSpeakersBtn->setClickedCallback(boost::bind(&LLVoiceRemoteCtrl::onClickSpeakers)); childSetAction("show_channel", onClickPopupBtn, this); childSetAction("end_call_btn", onClickEndCall, this); @@ -216,7 +214,7 @@ void LLVoiceRemoteCtrl::draw() LLPanel::draw(); } -void LLVoiceRemoteCtrl::onBtnTalkClicked(void *user_data) +void LLVoiceRemoteCtrl::onBtnTalkClicked() { // when in toggle mode, clicking talk button turns mic on/off if (gSavedSettings.getBOOL("PushToTalkToggle")) @@ -225,7 +223,7 @@ void LLVoiceRemoteCtrl::onBtnTalkClicked(void *user_data) } } -void LLVoiceRemoteCtrl::onBtnTalkHeld(void *user_data) +void LLVoiceRemoteCtrl::onBtnTalkHeld() { // when not in toggle mode, holding down talk button turns on mic if (!gSavedSettings.getBOOL("PushToTalkToggle")) @@ -234,7 +232,7 @@ void LLVoiceRemoteCtrl::onBtnTalkHeld(void *user_data) } } -void LLVoiceRemoteCtrl::onBtnTalkReleased(void* user_data) +void LLVoiceRemoteCtrl::onBtnTalkReleased() { // when not in toggle mode, releasing talk button turns off mic if (!gSavedSettings.getBOOL("PushToTalkToggle")) @@ -279,7 +277,7 @@ void LLVoiceRemoteCtrl::onClickEndCall(void* user_data) } -void LLVoiceRemoteCtrl::onClickSpeakers(void *user_data) +void LLVoiceRemoteCtrl::onClickSpeakers() { LLFloaterActiveSpeakers::toggleInstance(LLSD()); } diff --git a/indra/newview/llvoiceremotectrl.h b/indra/newview/llvoiceremotectrl.h index 1f61459ff..8522a6f37 100644 --- a/indra/newview/llvoiceremotectrl.h +++ b/indra/newview/llvoiceremotectrl.h @@ -47,10 +47,10 @@ public: /*virtual*/ void draw(); static void onBtnLock(void* user_data); - static void onBtnTalkHeld(void *user_data); - static void onBtnTalkReleased(void* user_data); - static void onBtnTalkClicked(void* user_data); - static void onClickSpeakers(void *user_data); + static void onBtnTalkHeld(); + static void onBtnTalkReleased(); + static void onBtnTalkClicked(); + static void onClickSpeakers(); static void onClickPopupBtn(void* user_data); static void onClickVoiceChannel(void* user_data); static void onClickEndCall(void* user_data); diff --git a/indra/newview/llvoinventorylistener.cpp b/indra/newview/llvoinventorylistener.cpp index 5e9b88042..1ea90c6a9 100644 --- a/indra/newview/llvoinventorylistener.cpp +++ b/indra/newview/llvoinventorylistener.cpp @@ -2,31 +2,25 @@ * @file llvoinventorylistener.cpp * @brief Interface for classes that wish to receive updates about viewer object inventory * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/newview/llvoinventorylistener.h b/indra/newview/llvoinventorylistener.h index 1531e6e33..bf14d19b0 100644 --- a/indra/newview/llvoinventorylistener.h +++ b/indra/newview/llvoinventorylistener.h @@ -2,31 +2,25 @@ * @file llvoinventorylistener.h * @brief Interface for classes that wish to receive updates about viewer object inventory * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 64ab53b88..434c8ca64 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -49,11 +49,149 @@ #include "llviewerregion.h" #include "pipeline.h" #include "llspatialpartition.h" +#include "llviewerobjectlist.h" const F32 MAX_PART_LIFETIME = 120.f; extern U64 gFrameTime; +LLPointer LLVOPartGroup::sVB = NULL; +S32 LLVOPartGroup::sVBSlotFree[]; +S32* LLVOPartGroup::sVBSlotCursor = NULL; + +//static +void LLVOPartGroup::restoreGL() +{ + for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) + { + sVBSlotFree[i] = i; + } + + sVBSlotCursor = sVBSlotFree; + + sVB = new LLVertexBuffer(VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + U32 count = LL_MAX_PARTICLE_COUNT; + sVB->allocateBuffer(count*4, count*6, true); + + //indices and texcoords are always the same, set once + LLStrider indicesp; + + LLStrider verticesp; + + sVB->getIndexStrider(indicesp); + sVB->getVertexStrider(verticesp); + + LLVector4a v; + v.set(0,0,0,0); + + + U16 vert_offset = 0; + + for (U32 i = 0; i < LL_MAX_PARTICLE_COUNT; i++) + { + *indicesp++ = vert_offset + 0; + *indicesp++ = vert_offset + 1; + *indicesp++ = vert_offset + 2; + + *indicesp++ = vert_offset + 1; + *indicesp++ = vert_offset + 3; + *indicesp++ = vert_offset + 2; + + *verticesp++ = v; + + vert_offset += 4; + } + + LLStrider texcoordsp; + sVB->getTexCoord0Strider(texcoordsp); + + for (U32 i = 0; i < LL_MAX_PARTICLE_COUNT; i++) + { + *texcoordsp++ = LLVector2(0.f, 1.f); + *texcoordsp++ = LLVector2(0.f, 0.f); + *texcoordsp++ = LLVector2(1.f, 1.f); + *texcoordsp++ = LLVector2(1.f, 0.f); + } + + sVB->flush(); + +} + +//static +void LLVOPartGroup::destroyGL() +{ + //Just iterate over all particle faces and mark their vbo index as 'uninitialized' since sVBSlotFree & sVBSlotCursor will be clobbered. + for (int i=0; imDrawable) + { + if (obj->mDrawable->getRenderType() == LLPipeline::RENDER_TYPE_PARTICLES || + obj->mDrawable->getRenderType() == LLPipeline::RENDER_TYPE_HUD_PARTICLES +#if ENABLE_CLASSIC_CLOUDS + || obj->mDrawable->getRenderType() == LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS +#endif + ) + { + for (S32 j = 0; j < obj->mDrawable->getNumFaces(); ++j) + { + LLFace* facep = obj->mDrawable->getFace(j); + if(facep) + facep->setIndicesIndex(0xFFFFFFFF); + } + } + } + } + for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) + { + sVBSlotFree[i] = i; + } + sVB = NULL; +} + +//static +S32 LLVOPartGroup::findAvailableVBSlot() +{ + if (sVBSlotCursor >= sVBSlotFree+LL_MAX_PARTICLE_COUNT) + { //no more available slots + return -1; + } + + S32 ret = *sVBSlotCursor; + sVBSlotCursor++; + + + return ret; +} + +bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end) +{ + while (start < end) + { + if (*start == idx) + { //not allocated (in free list) + return false; + } + ++start; + } + + //allocated (not in free list) + return true; +} + +//static +void LLVOPartGroup::freeVBSlot(S32 idx) +{ + llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); + llassert(sVBSlotCursor > sVBSlotFree); + llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); + + if (sVBSlotCursor > sVBSlotFree) + { + sVBSlotCursor--; + *sVBSlotCursor = idx; + } +} LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : LLAlphaObject(id, pcode, regionp), mViewerPartGroupp(NULL) @@ -287,9 +425,6 @@ void LLVOPartGroup::getGeometry(S32 idx, const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx])); - U32 vert_offset = mDrawable->getFace(idx)->getGeomIndex(); - - LLVector4a part_pos_agent; part_pos_agent.load3(part.mPosAgent.mV); LLVector4a camera_agent; @@ -361,33 +496,18 @@ void LLVOPartGroup::getGeometry(S32 idx, verticesp->setAdd(ppamu, right); (*verticesp++).getF32ptr()[3] = 0.f; - // *verticesp++ = part_pos_agent + up - right; - // *verticesp++ = part_pos_agent - up - right; - // *verticesp++ = part_pos_agent + up + right; - // *verticesp++ = part_pos_agent - up + right; - *colorsp++ = part.mColor; *colorsp++ = part.mColor; *colorsp++ = part.mColor; *colorsp++ = part.mColor; - *texcoordsp++ = LLVector2(0.f, 1.f); - *texcoordsp++ = LLVector2(0.f, 0.f); - *texcoordsp++ = LLVector2(1.f, 1.f); - *texcoordsp++ = LLVector2(1.f, 0.f); - - *normalsp++ = normal; - *normalsp++ = normal; - *normalsp++ = normal; - *normalsp++ = normal; - - *indicesp++ = vert_offset + 0; - *indicesp++ = vert_offset + 1; - *indicesp++ = vert_offset + 2; - - *indicesp++ = vert_offset + 1; - *indicesp++ = vert_offset + 3; - *indicesp++ = vert_offset + 2; + if (!(part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK)) + { //not fullbright, needs normal + *normalsp++ = normal; + *normalsp++ = normal; + *normalsp++ = normal; + *normalsp++ = normal; + } } U32 LLVOPartGroup::getPartitionType() const @@ -412,6 +532,49 @@ LLHUDParticlePartition::LLHUDParticlePartition() : mPartitionType = LLViewerRegion::PARTITION_HUD_PARTICLE; } +static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VBO("Particle VBO"); + +void LLParticlePartition::rebuildGeom(LLSpatialGroup* group) +{ + if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) + { + return; + } + + if (group->changeLOD()) + { + group->mLastUpdateDistance = group->mDistance; + group->mLastUpdateViewAngle = group->mViewAngle; + } + + LLFastTimer ftm(FTM_REBUILD_PARTICLE_VBO); + + group->clearDrawMap(); + + //get geometry count + U32 index_count = 0; + U32 vertex_count = 0; + + addGeometryCount(group, vertex_count, index_count); + + + if (vertex_count > 0 && index_count > 0) + { + group->mBuilt = 1.f; + //use one vertex buffer for all groups + group->mVertexBuffer = LLVOPartGroup::sVB; + getGeometry(group); + } + else + { + group->mVertexBuffer = NULL; + group->mBufferMap.clear(); + } + + group->mLastUpdateTime = gFrameTimeSeconds; + group->clearState(LLSpatialGroup::GEOM_DIRTY); +} + void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count) { group->mBufferUsage = mBufferUsage; @@ -431,11 +594,6 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get(); obj->mDepth = 0.f; - if (drawablep->isAnimating()) - { - group->mBufferUsage = GL_STREAM_DRAW_ARB; - } - U32 count = 0; for (S32 j = 0; j < drawablep->getNumFaces(); ++j) { @@ -447,13 +605,14 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co continue; } + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + count++; facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis(); obj->mDepth += facep->mDistance; mFaceList.push_back(facep); - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); llassert(facep->getIndicesCount() < 65536); } @@ -461,15 +620,13 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co } } -static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB"); -static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VB("Particle VB"); + +static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_GEOM("Particle Geom"); void LLParticlePartition::getGeometry(LLSpatialGroup* group) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ? - FTM_REBUILD_GRASS_VB : - FTM_REBUILD_PARTICLE_VB); + LLFastTimer ftm(FTM_REBUILD_PARTICLE_GEOM); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); @@ -489,21 +646,44 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) buffer->getVertexStrider(verticesp); buffer->getNormalStrider(normalsp); buffer->getColorStrider(colorsp); - buffer->getTexCoord0Strider(texcoordsp); - buffer->getIndexStrider(indicesp); - + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; for (std::vector::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) { LLFace* facep = *i; LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); - facep->setGeomIndex(vertex_count); - facep->setIndicesIndex(index_count); - facep->setVertexBuffer(buffer); - facep->setPoolType(LLDrawPool::POOL_ALPHA); - object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + + if (facep->getIndicesStart() == 0xFFFFFFFF) + { //set the indices of this face + S32 idx = LLVOPartGroup::findAvailableVBSlot(); + if (idx >= 0) + { + facep->setGeomIndex(idx*4); + facep->setIndicesIndex(idx*6); + facep->setVertexBuffer(LLVOPartGroup::sVB); + facep->setPoolType(LLDrawPool::POOL_ALPHA); + } + else + { + continue; //out of space in particle buffer + } + } + + S32 geom_idx = (S32) facep->getGeomIndex(); + + LLStrider cur_idx = indicesp + facep->getIndicesStart(); + LLStrider cur_vert = verticesp + geom_idx; + LLStrider cur_norm = normalsp + geom_idx; + LLStrider cur_tc = texcoordsp + geom_idx; + LLStrider cur_col = colorsp + geom_idx; + + object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_idx); + llassert(facep->getGeomCount() == 4); + llassert(facep->getIndicesCount() == 6); + + vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); @@ -512,26 +692,39 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); F32 vsize = facep->getVirtualSize(); - if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + bool batched = false; + + if (idx >= 0 && draw_vec[idx]->mTexture == facep->getTexture() && - (U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange && - //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && - draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 && draw_vec[idx]->mFullbright == fullbright) { - draw_vec[idx]->mCount += facep->getIndicesCount(); - draw_vec[idx]->mEnd += facep->getGeomCount(); - draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1) + { + batched = true; + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } + else if (draw_vec[idx]->mStart == facep->getGeomIndex()+facep->getGeomCount()+1) + { + batched = true; + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mStart -= facep->getGeomCount(); + draw_vec[idx]->mOffset = facep->getIndicesStart(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } } - else + + + if (!batched) { U32 start = facep->getGeomIndex(); U32 end = start + facep->getGeomCount()-1; U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); - LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), + LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), //facep->getTexture(), - buffer, fullbright); + buffer, fullbright); info->mExtents[0] = group->mObjectExtents[0]; info->mExtents[1] = group->mObjectExtents[1]; info->mVSize = vsize; @@ -541,7 +734,6 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) } } - buffer->flush(); mFaceList.clear(); } diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index f11289365..4c2e073d7 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -37,18 +37,32 @@ #include "v3math.h" #include "v3color.h" #include "llframetimer.h" +#include "llviewerpartsim.h" +#include "llvertexbuffer.h" class LLViewerPartGroup; class LLVOPartGroup : public LLAlphaObject { public: + + //vertex buffer for holding all particles + static LLPointer sVB; + static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT]; + static S32* sVBSlotCursor; + + static void restoreGL(); + static void destroyGL(); + static S32 findAvailableVBSlot(); + static void freeVBSlot(S32 idx); + enum { - VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | - (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD0) | - (1 << LLVertexBuffer::TYPE_COLOR) + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_TEXTURE_INDEX }; LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 610697742..a16b4adc9 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -302,18 +302,20 @@ void LLVOSurfacePatch::updateFaceSize(S32 idx) } LLFace* facep = mDrawable->getFace(idx); - - S32 num_vertices = 0; - S32 num_indices = 0; - - if (mLastStride) + if (facep) { - getGeomSizesMain(mLastStride, num_vertices, num_indices); - getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices); - getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices); - } + S32 num_vertices = 0; + S32 num_indices = 0; + + if (mLastStride) + { + getGeomSizesMain(mLastStride, num_vertices, num_indices); + getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices); + getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices); + } - facep->setSize(num_vertices, num_indices); + facep->setSize(num_vertices, num_indices); + } } BOOL LLVOSurfacePatch::updateLOD() @@ -328,30 +330,32 @@ void LLVOSurfacePatch::getGeometry(LLStrider &verticesp, LLStrider &indicesp) { LLFace* facep = mDrawable->getFace(0); + if (facep) + { + U32 index_offset = facep->getGeomIndex(); - U32 index_offset = facep->getGeomIndex(); - - updateMainGeometry(facep, - verticesp, - normalsp, - texCoords0p, - texCoords1p, - indicesp, - index_offset); - updateNorthGeometry(facep, - verticesp, - normalsp, - texCoords0p, - texCoords1p, - indicesp, - index_offset); - updateEastGeometry(facep, + updateMainGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, index_offset); + updateNorthGeometry(facep, + verticesp, + normalsp, + texCoords0p, + texCoords1p, + indicesp, + index_offset); + updateEastGeometry(facep, + verticesp, + normalsp, + texCoords0p, + texCoords1p, + indicesp, + index_offset); + } } void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, @@ -870,7 +874,11 @@ void LLVOSurfacePatch::dirtyGeom() if (mDrawable) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); - mDrawable->getFace(0)->setVertexBuffer(NULL); + LLFace* facep = mDrawable->getFace(0); + if (facep) + { + facep->setVertexBuffer(NULL); + } mDrawable->movePartition(); } } diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 39886e8fb..e50c11ced 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -58,7 +58,8 @@ #include "pipeline.h" #include "llspatialpartition.h" #include "llnotificationsutil.h" -#include "llviewerwindow.h" +#include "raytrace.h" +#include "llglslshader.h" extern LLPipeline gPipeline; @@ -504,11 +505,16 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) if(mTrunkLOD >= sMAX_NUM_TREE_LOD_LEVELS) //do not display the tree. { mReferenceBuffer = NULL ; - mDrawable->getFace(0)->setVertexBuffer(NULL); + LLFace * facep = drawable->getFace(0); + if (facep) + { + facep->setVertexBuffer(NULL); + } return TRUE ; } - if (mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer()) + if (mDrawable->getFace(0) && + (mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer())) { const F32 SRR3 = 0.577350269f; // sqrt(1/3) const F32 SRR2 = 0.707106781f; // sqrt(1/2) @@ -521,6 +527,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) S32 lod; LLFace *face = drawable->getFace(0); + if (!face) return TRUE; face->mCenterAgent = getPositionAgent(); face->mCenterLocal = face->mCenterAgent; @@ -894,6 +901,7 @@ void LLVOTree::updateMesh() calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches); LLFace* facep = mDrawable->getFace(0); + if (!facep) return; LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); buff->allocateBuffer(vert_count, index_count, TRUE); facep->setVertexBuffer(buff); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index d487567b1..1d6167195 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -39,6 +39,7 @@ #include "llviewercontrol.h" #include "lldir.h" #include "llflexibleobject.h" +#include "llfloatertools.h" #include "llmaterialtable.h" #include "llprimitive.h" #include "llvolume.h" @@ -50,6 +51,7 @@ #include "object_flags.h" #include "llagentconstants.h" #include "lldrawable.h" +#include "lldrawpoolavatar.h" #include "lldrawpoolbump.h" #include "llface.h" #include "llspatialpartition.h" @@ -68,17 +70,16 @@ #include "pipeline.h" #include "llsdutil.h" #include "llmatrix4a.h" -#include "llagent.h" -#include "lldrawpoolavatar.h" #include "llmeshrepository.h" +#include "llagent.h" #include "lldatapacker.h" #include "llviewershadermgr.h" #include "llvoavatar.h" -#include "llfloatertools.h" #include "llvocache.h" // [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0d) #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] const S32 MIN_QUIET_FRAMES_COALESCE = 30; @@ -130,7 +131,7 @@ void LLVOVolume::markDead() { if (!mDead) { - + if (mSculptTexture.notNull()) { mSculptTexture->removeVolume(this); @@ -309,7 +310,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, } } } - + return retval; } @@ -337,6 +338,7 @@ void LLVOVolume::animateTextures() for (S32 i = start; i <= end; i++) { LLFace* facep = mDrawable->getFace(i); + if (!facep) continue; if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; const LLTextureEntry* te = facep->getTextureEntry(); @@ -428,7 +430,7 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { LLViewerObject::idleUpdate(agent, world, time); - static LLFastTimer::DeclareTimer ftm("Volume"); + static LLFastTimer::DeclareTimer ftm("Volume Idle"); LLFastTimer t(ftm); if (mDead || mDrawable.isNull()) @@ -473,6 +475,20 @@ void LLVOVolume::updateTextures() if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) { updateTextureVirtualSize(); + + if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive()) + { //delete vertex buffer to free up some VRAM + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->destroyGL(true); + + //flag the group as having changed geometry so it gets a rebuild next time + //it becomes visible + group->setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } + } + } } @@ -507,8 +523,19 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) if(!forced) { if(!isVisible()) - { - return; + { //don't load textures for non-visible faces + const S32 num_faces = mDrawable->getNumFaces(); + for (S32 i = 0; i < num_faces; i++) + { + LLFace* face = mDrawable->getFace(i); + if (face) + { + face->setPixelArea(0.f); + face->setVirtualSize(0.f); + } + } + + return ; } if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) @@ -535,6 +562,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) for (S32 i = 0; i < num_faces; i++) { LLFace* face = mDrawable->getFace(i); + if (!face) continue; const LLTextureEntry *te = face->getTextureEntry(); LLViewerTexture *imagep = face->getTexture(); if (!imagep || !te || @@ -567,19 +595,9 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) } mPixelArea = llmax(mPixelArea, face->getPixelArea()); - + if (face->mTextureMatrix != NULL) { - // Animating textures also rez badly in Snowglobe because the - // actual displayed area is only a fraction (corresponding to one - // frame) of the animating texture. Let's fix that here: - /* if (mTextureAnimp && mTextureAnimp->mScaleS > 0.0f && mTextureAnimp->mScaleT > 0.0f) - { - // Adjust to take into account the actual frame size which is only a - // portion of the animating texture - vsize = vsize / mTextureAnimp->mScaleS / mTextureAnimp->mScaleT; - }*/ - if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) { @@ -655,6 +673,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) mSculptTexture->getHeight(), mSculptTexture->getWidth())); } } + } if (getLightTextureID().notNull()) @@ -835,7 +854,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo { mVolumeImpl->onSetVolume(volume_params, mLOD); //detail ? } - + updateSculptTexture(); if (isSculpted()) @@ -865,6 +884,27 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo } } + + static LLCachedControl use_transform_feedback("RenderUseTransformFeedback", false); + + bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject && + (!mVolumeImpl || !mVolumeImpl->isVolumeUnique()); + + if (cache_in_vram) + { //this volume might be used as source data for a transform object, put it in vram + LLVolume* volume = getVolume(); + for (S32 i = 0; i < volume->getNumFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + if (face.mVertexBuffer.notNull()) + { //already cached + break; + } + volume->genBinormals(i); + LLFace::cacheFaceInVRAM(face); + } + } + return TRUE; } return FALSE; @@ -949,6 +989,7 @@ void LLVOVolume::sculpt() if(!raw_image) { llassert(discard_level < 0) ; + sculpt_width = 0; sculpt_height = 0; sculpt_data = NULL ; @@ -1017,7 +1058,7 @@ BOOL LLVOVolume::calcLOD() distance *= sDistanceFactor; - + F32 rampDist = LLVOVolume::sLODFactor * 2; if (distance < rampDist) @@ -1033,7 +1074,8 @@ BOOL LLVOVolume::calcLOD() llround(radius, 0.01f)); - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO)) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && + mDrawable->getFace(0)) { //setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail)); @@ -1112,25 +1154,23 @@ void LLVOVolume::updateFaceFlags() for (S32 i = 0; i < getVolume()->getNumFaces(); i++) { LLFace *face = mDrawable->getFace(i); - if (!face) + if (face) { - return; - } + BOOL fullbright = getTE(i)->getFullbright(); + face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); - BOOL fullbright = getTE(i)->getFullbright(); - face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); - - if (fullbright || (mMaterial == LL_MCODE_LIGHT)) - { - face->setState(LLFace::FULLBRIGHT); - } - if (mDrawable->isLight()) - { - face->setState(LLFace::LIGHT); - } - if (isHUDAttachment()) - { - face->setState(LLFace::HUD_RENDER); + if (fullbright || (mMaterial == LL_MCODE_LIGHT)) + { + face->setState(LLFace::FULLBRIGHT); + } + if (mDrawable->isLight()) + { + face->setState(LLFace::LIGHT); + } + if (isHUDAttachment()) + { + face->setState(LLFace::HUD_RENDER); + } } } } @@ -1167,6 +1207,8 @@ void LLVOVolume::regenFaces() for (S32 i = 0; i < mNumFaces; i++) { LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); + if (!facep) continue; + facep->setTEOffset(i); facep->setTexture(getTEImage(i)); facep->setViewerObject(this); @@ -1189,7 +1231,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); -// bool rigged = false; + // bool rigged = false; LLVolume* volume = mRiggedVolume; if (!volume) { @@ -1244,11 +1286,11 @@ void LLVOVolume::preRebuild() } } -void LLVOVolume::updateRelativeXform() +void LLVOVolume::updateRelativeXform(bool force_identity) { if (mVolumeImpl) { - mVolumeImpl->updateRelativeXform(); + mVolumeImpl->updateRelativeXform(force_identity); return; } @@ -1268,15 +1310,16 @@ void LLVOVolume::updateRelativeXform() mRelativeXform.invert(); mRelativeXformInvTrans.transpose(); } - else if (drawable->isActive()) + else if (drawable->isActive() || force_identity) { // setup relative transforms LLQuaternion delta_rot; LLVector3 delta_pos, delta_scale; //matrix from local space to parent relative/global space - delta_rot = drawable->isSpatialRoot() ? LLQuaternion() : mDrawable->getRotation(); - delta_pos = drawable->isSpatialRoot() ? LLVector3(0,0,0) : mDrawable->getPosition(); + bool use_identity = force_identity || drawable->isSpatialRoot(); + delta_rot = use_identity ? LLQuaternion() : mDrawable->getRotation(); + delta_pos = use_identity ? LLVector3(0,0,0) : mDrawable->getPosition(); delta_scale = mDrawable->getScale(); // Vertex transform (4x4) @@ -1377,7 +1420,11 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) return res; } - dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + LLSpatialGroup* group = drawable->getSpatialGroup(); + if (group) + { + group->dirtyMesh(); + } BOOL compiled = FALSE; @@ -1388,8 +1435,10 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) return TRUE; // No update to complete } - if (mVolumeChanged || mFaceMappingChanged ) + if (mVolumeChanged || mFaceMappingChanged || mDrawable->isState(LLDrawable::REBUILD_MATERIAL)) { + dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + compiled = TRUE; if (mVolumeChanged) @@ -1408,6 +1457,8 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) } else if ((mLODChanged) || (mSculptChanged)) { + dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + LLVolume *old_volumep, *new_volumep; F32 old_lod, new_lod; S32 old_num_faces, new_num_faces ; @@ -1489,16 +1540,19 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) void LLVOVolume::updateFaceSize(S32 idx) { LLFace* facep = mDrawable->getFace(idx); - if (idx >= getVolume()->getNumVolumeFaces()) + if (facep) { - facep->setSize(0,0, true); - } - else - { - const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); - facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, - true); // <--- volume faces should be padded for 16-byte alignment + if (idx >= getVolume()->getNumVolumeFaces()) + { + facep->setSize(0,0, true); + } + else + { + const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); + facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, + true); // <--- volume faces should be padded for 16-byte alignment + } } } @@ -2037,7 +2091,7 @@ BOOL LLVOVolume::isSculpted() const } BOOL LLVOVolume::isMesh() const -{ +{ if (isSculpted()) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); @@ -2336,9 +2390,10 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const produces_light = 1; } - for (U32 i = 0; i < num_faces; ++i) + for (S32 i = 0; i < num_faces; ++i) { const LLFace* face = drawablep->getFace(i); + if (!face) continue; const LLTextureEntry* te = face->getTextureEntry(); const LLViewerTexture* img = face->getTexture(); @@ -2614,6 +2669,7 @@ F32 LLVOVolume::getBinRadius() for (S32 i = 0; i < mDrawable->getNumFaces(); i++) { LLFace* face = mDrawable->getFace(i); + if (!face) continue; if (face->getPoolType() == LLDrawPool::POOL_ALPHA && !face->canRenderAsMask()) { @@ -2695,9 +2751,12 @@ LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const { LLVector3 ret = pos - getRenderPosition(); ret = ret * ~getRenderRotation(); - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - ret.scaleVec(invObjScale); + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + ret.scaleVec(invObjScale); + } return ret; } @@ -2715,8 +2774,12 @@ LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const { LLVector3 ret = dir; - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - ret.scaleVec(objScale); + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + ret.scaleVec(objScale); + } + ret = ret * getRenderRotation(); ret += getRenderPosition(); @@ -2844,7 +2907,8 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e { LLFace* face = mDrawable->getFace(face_hit); - if (pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n))) + if (face && + (pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))) { v_end = p; if (face_hitp != NULL) @@ -3154,15 +3218,20 @@ bool can_batch_texture(LLFace* facep) return true; } +static LLFastTimer::DeclareTimer FTM_REGISTER_FACE("Register Face"); + void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) { + LLFastTimer t(FTM_REGISTER_FACE); LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); // if (facep->getViewerObject()->isSelected() && gHideSelectedObjects) -// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.1.3b) | Modified: RLVa-1.2.1f +// [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c const LLViewerObject* pObj = facep->getViewerObject(); if ( (pObj->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects) && - ((!rlv_handler_t::isEnabled()) || (!pObj->isHUDAttachment()) || (!gRlvAttachmentLocks.isLockedAttachment(pObj->getRootEdit()))) ) + ( (!rlv_handler_t::isEnabled()) || + ( ((!pObj->isHUDAttachment()) || (!gRlvAttachmentLocks.isLockedAttachment(pObj->getRootEdit()))) && + (gRlvHandler.canEdit(pObj)) ) ) ) // [/RLVa:KB] { return; @@ -3192,9 +3261,14 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, const LLMatrix4* model_mat = NULL; LLDrawable* drawable = facep->getDrawable(); - if (drawable->isActive()) + + if (drawable->isState(LLDrawable::ANIMATED_CHILD)) { - model_mat = &(drawable->getRenderMatrix()); + model_mat = &drawable->getWorldMatrix(); + } + else if (drawable->isActive()) + { + model_mat = &drawable->getRenderMatrix(); } else { @@ -3205,6 +3279,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, } } + //drawable->getVObj()->setDebugText(llformat("%d", drawable->isState(LLDrawable::ANIMATED_CHILD))); + U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0; LLViewerTexture* tex = facep->getTexture(); @@ -3293,8 +3369,9 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) } -static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume"); -static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume VB"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_FACE_LIST("Build Face List"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_GEN_DRAW_INFO("Gen Draw Info"); static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) { @@ -3341,19 +3418,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (group->isState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) { - LLFastTimer ftm(FTM_REBUILD_VBO); - LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); - rebuildMesh(group); } return; } + LLFastTimer ftm(FTM_REBUILD_VOLUME_VB); + group->mBuilt = 1.f; - LLFastTimer ftm(FTM_REBUILD_VBO); - - LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); - + LLVOAvatar* pAvatarVO = NULL; LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); @@ -3380,6 +3453,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) group->mGeometryBytes = 0; group->mSurfaceArea = 0; + //cache object box size since it might be used for determining visibility + group->mObjectBoxSize = group->mObjectBounds[1].getLength3().getF32(); + group->clearDrawMap(); mFaceList.clear(); @@ -3401,359 +3477,375 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) bool emissive = false; - //get all the faces into a list - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { - LLDrawable* drawablep = *drawable_iter; + LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST); + + //get all the faces into a list + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLDrawable* drawablep = *drawable_iter; - if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) - { - continue; - } - - if (drawablep->isAnimating()) - { //fall back to stream draw for animating verts - useage = GL_STREAM_DRAW_ARB; - } - - LLVOVolume* vobj = drawablep->getVOVolume(); - - if (!vobj) - { - continue; - } - - if (vobj->isMesh() && - (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled())) - { - continue; - } - - LLVolume* volume = vobj->getVolume(); - if (volume) - { - const LLVector3& scale = vobj->getScale(); - group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); - } - - llassert_always(vobj); - vobj->updateTextureVirtualSize(true); - vobj->preRebuild(); - - drawablep->clearState(LLDrawable::HAS_ALPHA); - - bool rigged = vobj->isAttachment() && - vobj->isMesh() && - gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); - - bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); - - bool is_rigged = false; - - //for each face - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - LLFace* facep = drawablep->getFace(i); - - //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render - // batch, it will recover its vertex buffer reference from the spatial group - facep->setVertexBuffer(NULL); - - //sum up face verts and indices - drawablep->updateFaceSize(i); - - - - if (rigged) + if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) { - if (!facep->isState(LLFace::RIGGED)) - { //completely reset vertex buffer - facep->clearVertexBuffer(); - } - - facep->setState(LLFace::RIGGED); - is_rigged = true; - - //get drawpool of avatar with rigged face - LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); - - //Determine if we've received skininfo that contains an - //alternate bind matrix - if it does then apply the translational component - //to the joints of the avatar. - bool pelvisGotSet = false; + continue; + } + + if (drawablep->isAnimating()) + { //fall back to stream draw for animating verts + useage = GL_STREAM_DRAW_ARB; + } - if ( pAvatarVO ) + LLVOVolume* vobj = drawablep->getVOVolume(); + + if (!vobj) + { + continue; + } + + if ((vobj->isMesh() && + (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) + { + continue; + } + + LLVolume* volume = vobj->getVolume(); + if (volume) + { + const LLVector3& scale = vobj->getScale(); + group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); + } + + llassert_always(vobj); + vobj->updateTextureVirtualSize(true); + vobj->preRebuild(); + + drawablep->clearState(LLDrawable::HAS_ALPHA); + + bool rigged = vobj->isAttachment() && + vobj->isMesh() && + gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); + + bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); + + bool is_rigged = false; + + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + LLFace* facep = drawablep->getFace(i); + if (!facep) { - LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); - const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); - - if ( pSkinData ) + continue; + } + + //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render + // batch, it will recover its vertex buffer reference from the spatial group + facep->setVertexBuffer(NULL); + + //sum up face verts and indices + drawablep->updateFaceSize(i); + + + + if (rigged) + { + if (!facep->isState(LLFace::RIGGED)) + { //completely reset vertex buffer + facep->clearVertexBuffer(); + } + + facep->setState(LLFace::RIGGED); + is_rigged = true; + + //get drawpool of avatar with rigged face + LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); + + //Determine if we've received skininfo that contains an + //alternate bind matrix - if it does then apply the translational component + //to the joints of the avatar. + bool pelvisGotSet = false; + + if ( pAvatarVO ) { - const int bindCnt = pSkinData->mAlternateBindMatrix.size(); - if ( bindCnt > 0 ) - { - const int jointCnt = pSkinData->mJointNames.size(); - const F32 pelvisZOffset = pSkinData->mPelvisOffset; - bool fullRig = (jointCnt>=20) ? true : false; - if ( fullRig ) - { - for ( int i=0; igetVolume()->getParams().getSculptID(); + const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); + + if ( pSkinData ) + { + const int bindCnt = pSkinData->mAlternateBindMatrix.size(); + if ( bindCnt > 0 ) + { + const int jointCnt = pSkinData->mJointNames.size(); + const F32 pelvisZOffset = pSkinData->mPelvisOffset; + bool fullRig = (jointCnt>=20) ? true : false; + if ( fullRig ) { - std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); - //llinfos<<"joint name "<getJoint( lookingForJoint ); - if ( pJoint && pJoint->getId() != currentId ) - { - pJoint->setId( currentId ); - const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); - //Set the joint position - pJoint->storeCurrentXform( jointPos ); - //If joint is a pelvis then handle old/new pelvis to foot values - if ( lookingForJoint == "mPelvis" ) - { + for ( int i=0; imJointNames[i].c_str(); + //llinfos<<"joint name "<getJoint( lookingForJoint ); + if ( pJoint && pJoint->getId() != currentId ) + { + pJoint->setId( currentId ); + const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); + //Set the joint position pJoint->storeCurrentXform( jointPos ); - if ( !pAvatarVO->hasPelvisOffset() ) - { - pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); - //Trigger to rebuild viewer AV - pelvisGotSet = true; + //If joint is a pelvis then handle old/new pelvis to foot values + if ( lookingForJoint == "mPelvis" ) + { + pJoint->storeCurrentXform( jointPos ); + if ( !pAvatarVO->hasPelvisOffset() ) + { + pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); + //Trigger to rebuild viewer AV + pelvisGotSet = true; + } } - } + } } - } - } + } + } } } - } - //If we've set the pelvis to a new position we need to also rebuild some information that the - //viewer does at launch (e.g. body size etc.) - if ( pelvisGotSet ) - { - pAvatarVO->postPelvisSetRecalc(); - } - - if (pool) - { - const LLTextureEntry* te = facep->getTextureEntry(); - - //remove face from old pool if it exists - LLDrawPool* old_pool = facep->getPool(); - if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) + //If we've set the pelvis to a new position we need to also rebuild some information that the + //viewer does at launch (e.g. body size etc.) + if ( pelvisGotSet ) { - ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); + pAvatarVO->postPelvisSetRecalc(); } - //add face to new pool - LLViewerTexture* tex = facep->getTexture(); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - - if (type == LLDrawPool::POOL_ALPHA) + if (pool) { - if (te->getColor().mV[3] > 0.f) + const LLTextureEntry* te = facep->getTextureEntry(); + + //remove face from old pool if it exists + LLDrawPool* old_pool = facep->getPool(); + if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) + { + ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); + } + + //add face to new pool + LLViewerTexture* tex = facep->getTexture(); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + + if (type == LLDrawPool::POOL_ALPHA) + { + if (te->getColor().mV[3] > 0.f) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + } + } + } + else if (te->getShiny()) { if (te->getFullbright()) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); } else { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + if (LLPipeline::sRenderDeferred) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + } } } - } - else if (te->getShiny()) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); - } else { - if (LLPipeline::sRenderDeferred) + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); + } + else { pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); } - else + } + + if (te->getGlow()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); + } + + if (LLPipeline::sRenderDeferred) + { + if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + if (te->getBumpmap()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + } } } } - else - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - } - if (te->getGlow()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); - } - - if (LLPipeline::sRenderDeferred) - { - if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) - { - if (te->getBumpmap()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); - } - } - } - } - - continue; - } - else - { - if (facep->isState(LLFace::RIGGED)) - { //face is not rigged but used to be, remove from rigged face pool - LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); - if (pool) - { - pool->removeRiggedFace(facep); - } - facep->clearState(LLFace::RIGGED); - } - } - - - if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) - { - facep->clearVertexBuffer(); - continue; - } - - cur_total += facep->getGeomCount(); - - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) - { - const LLTextureEntry* te = facep->getTextureEntry(); - LLViewerTexture* tex = facep->getTexture(); - - if (te->getGlow() >= 1.f/255.f) - { - emissive = true; - } - - if (facep->isState(LLFace::TEXTURE_ANIM)) - { - if (!vobj->mTexAnimMode) - { - facep->clearState(LLFace::TEXTURE_ANIM); - } - } - - BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - if (type != LLDrawPool::POOL_ALPHA && force_simple) - { - type = LLDrawPool::POOL_SIMPLE; - } - facep->setPoolType(type); - - if (vobj->isHUDAttachment()) - { - facep->setState(LLFace::FULLBRIGHT); - } - - if (vobj->mTextureAnimp && vobj->mTexAnimMode) - { - if (vobj->mTextureAnimp->mFace <= -1) - { - S32 face; - for (face = 0; face < vobj->getNumTEs(); face++) - { - drawablep->getFace(face)->setState(LLFace::TEXTURE_ANIM); - } - } - else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) - { - drawablep->getFace(vobj->mTextureAnimp->mFace)->setState(LLFace::TEXTURE_ANIM); - } - } - - if (type == LLDrawPool::POOL_ALPHA) - { - if (facep->canRenderAsMask()) - { //can be treated as alpha mask - simple_faces.push_back(facep); - } - else - { - if (te->getColor().mV[3] > 0.f) - { //only treat as alpha in the pipeline if < 100% transparent - drawablep->setState(LLDrawable::HAS_ALPHA); - } - alpha_faces.push_back(facep); - } + continue; } else { - if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) + if (facep->isState(LLFace::RIGGED)) + { //face is not rigged but used to be, remove from rigged face pool + LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); + if (pool) + { + pool->removeRiggedFace(facep); + } + facep->clearState(LLFace::RIGGED); + } + } + + + if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) + { + facep->clearVertexBuffer(); + continue; + } + + cur_total += facep->getGeomCount(); + + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) + { + const LLTextureEntry* te = facep->getTextureEntry(); + LLViewerTexture* tex = facep->getTexture(); + + if (te->getGlow() >= 1.f/255.f) { - facep->mLastUpdateTime = gFrameTimeSeconds; + emissive = true; } - if (gPipeline.canUseWindLightShadersOnObjects() - && LLPipeline::sRenderBump) + if (facep->isState(LLFace::TEXTURE_ANIM)) { - if (te->getBumpmap()) - { //needs normal + binormal - bump_faces.push_back(facep); + if (!vobj->mTexAnimMode) + { + facep->clearState(LLFace::TEXTURE_ANIM); } - else if (te->getShiny() || !te->getFullbright()) - { //needs normal + } + + BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + if (type != LLDrawPool::POOL_ALPHA && force_simple) + { + type = LLDrawPool::POOL_SIMPLE; + } + facep->setPoolType(type); + + if (vobj->isHUDAttachment()) + { + facep->setState(LLFace::FULLBRIGHT); + } + + if (vobj->mTextureAnimp && vobj->mTexAnimMode) + { + if (vobj->mTextureAnimp->mFace <= -1) + { + S32 face; + for (face = 0; face < vobj->getNumTEs(); face++) + { + LLFace * facep = drawablep->getFace(face); + if (facep) + { + facep->setState(LLFace::TEXTURE_ANIM); + } + } + } + else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) + { + LLFace * facep = drawablep->getFace(vobj->mTextureAnimp->mFace); + if (facep) + { + facep->setState(LLFace::TEXTURE_ANIM); + } + } + } + + if (type == LLDrawPool::POOL_ALPHA) + { + if (facep->canRenderAsMask()) + { //can be treated as alpha mask simple_faces.push_back(facep); } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - fullbright_faces.push_back(facep); + else + { + if (te->getColor().mV[3] > 0.f) + { //only treat as alpha in the pipeline if < 100% transparent + drawablep->setState(LLDrawable::HAS_ALPHA); + } + alpha_faces.push_back(facep); } } else { - if (te->getBumpmap() && LLPipeline::sRenderBump) - { //needs normal + binormal - bump_faces.push_back(facep); + if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) + { + facep->mLastUpdateTime = gFrameTimeSeconds; } - else if ((te->getShiny() && LLPipeline::sRenderBump) || - !(te->getFullbright() || bake_sunlight)) - { //needs normal - simple_faces.push_back(facep); + + if (gPipeline.canUseWindLightShadersOnObjects() + && LLPipeline::sRenderBump) + { + if (te->getBumpmap()) + { //needs normal + binormal + bump_faces.push_back(facep); + } + else if (te->getShiny() || !te->getFullbright()) + { //needs normal + simple_faces.push_back(facep); + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); + fullbright_faces.push_back(facep); + } } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - fullbright_faces.push_back(facep); + else + { + if (te->getBumpmap() && LLPipeline::sRenderBump) + { //needs normal + binormal + bump_faces.push_back(facep); + } + else if ((te->getShiny() && LLPipeline::sRenderBump) || + !(te->getFullbright() || bake_sunlight)) + { //needs normal + simple_faces.push_back(facep); + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); + fullbright_faces.push_back(facep); + } } } } + else + { //face has no renderable geometry + facep->clearVertexBuffer(); + } + } + + if (is_rigged) + { + drawablep->setState(LLDrawable::RIGGED); } else - { //face has no renderable geometry - facep->clearVertexBuffer(); - } - } - - if (is_rigged) - { - drawablep->setState(LLDrawable::RIGGED); - } - else - { - drawablep->clearState(LLDrawable::RIGGED); + { + drawablep->clearState(LLDrawable::RIGGED); + } } } @@ -3820,15 +3912,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } } -static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry"); -static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM_PARTIAL("Terse Rebuild"); + void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { llassert(group); static int warningsCount = 20; if (group && group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY)) { - LLFastTimer tm(FTM_VOLUME_GEOM); + LLFastTimer ftm(FTM_REBUILD_VOLUME_VB); + LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers S32 num_mapped_vertex_buffer = LLVertexBuffer::sMappedCount ; group->mBuilt = 1.f; @@ -3837,19 +3929,18 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { - LLFastTimer t(FTM_VOLUME_GEOM_PARTIAL); LLDrawable* drawablep = *drawable_iter; - /*if (drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) - { - continue; - }*/ - - if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) ) + if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) { LLVOVolume* vobj = drawablep->getVOVolume(); vobj->preRebuild(); + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } + LLVolume* volume = vobj->getVolume(); for (S32 i = 0; i < drawablep->getNumFaces(); ++i) { @@ -3859,6 +3950,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) LLVertexBuffer* buff = face->getVertexBuffer(); if (buff) { + llassert(!face->isState(LLFace::RIGGED)); face->getGeometryVolume(*volume, face->getTEOffset(), vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); @@ -3869,6 +3961,12 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) } } } + + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(); + } + drawablep->clearState(LLDrawable::REBUILD_ALL); } @@ -3901,10 +3999,13 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) for (S32 i = 0; i < drawablep->getNumFaces(); ++i) { LLFace* face = drawablep->getFace(i); - LLVertexBuffer* buff = face ? face->getVertexBuffer() : NULL; - if (buff && buff->isLocked()) + if (face) { - buff->flush(); + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff && buff->isLocked()) + { + buff->flush(); + } } } } @@ -3913,7 +4014,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); } - llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); +// llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); } struct CompareBatchBreakerModified @@ -3939,10 +4040,22 @@ struct CompareBatchBreakerModified } }; +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_SORT("Draw Info Face Sort"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_FACE_SIZE("Face Sizing"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_ALLOCATE("Allocate VB"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_FIND_VB("Find VB"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); + + + + + void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector& faces, BOOL distance_sort, BOOL batch_textures) { - U32 buffer_usage = group->mBufferUsage; + LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); + U32 buffer_usage = group->mBufferUsage; + #if LL_DARWIN // HACK from Leslie: // Disable VBO usage for alpha on Mac OS X because it kills the framerate @@ -3959,15 +4072,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: U32 max_vertices = (render_max_vbo_size*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); max_vertices = llmin(max_vertices, (U32) 65535); - if (!distance_sort) { - //sort faces by things that break batches - std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified()); - } - else - { - //sort faces by distance - std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); + LLFastTimer t(FTM_GEN_DRAW_INFO_SORT); + if (!distance_sort) + { + //sort faces by things that break batches + std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified()); + } + else + { + //sort faces by distance + std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); + } } bool hud_group = group->isHUDGroup() ; @@ -3983,12 +4099,13 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: buffer_index = -1; } - S32 texture_index_channels = LLGLSLShader::sIndexedTextureChannels-1; //always reserve one for shiny for now just for simplicity + S32 texture_index_channels = 1; - static const LLCachedControl no_texture_indexing("ShyotlUseLegacyTextureBatching",false); - if (gGLManager.mGLVersion < 3.1f || no_texture_indexing) + if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) { - texture_index_channels = 1; + static const LLCachedControl no_texture_indexing("ShyotlUseLegacyTextureBatching",false); + if(!no_texture_indexing) + texture_index_channels = LLGLSLShader::sIndexedTextureChannels-1; //always reserve one for shiny for now just for simplicity; } if (LLPipeline::sRenderDeferred && distance_sort) @@ -4034,57 +4151,86 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: std::vector texture_list; - if (batch_textures) { - U8 cur_tex = 0; - facep->setTextureIndex(cur_tex); - texture_list.push_back(tex); - - //if (can_batch_texture(facep)) + LLFastTimer t(FTM_GEN_DRAW_INFO_FACE_SIZE); + if (batch_textures) { - while (i != faces.end()) + U8 cur_tex = 0; + facep->setTextureIndex(cur_tex); + texture_list.push_back(tex); + + //if (can_batch_texture(facep)) { - facep = *i; - if (facep->getTexture() != tex) + while (i != faces.end()) { - if (distance_sort) - { //textures might be out of order, see if texture exists in current batch - bool found = false; - for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx) - { - if (facep->getTexture() == texture_list[tex_idx]) + facep = *i; + if (facep->getTexture() != tex) + { + if (distance_sort) + { //textures might be out of order, see if texture exists in current batch + bool found = false; + for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx) { - cur_tex = tex_idx; - found = true; - break; + if (facep->getTexture() == texture_list[tex_idx]) + { + cur_tex = tex_idx; + found = true; + break; + } + } + + if (!found) + { + cur_tex = texture_list.size(); } } - - if (!found) + else { - cur_tex = texture_list.size(); + cur_tex++; } - } - else - { - cur_tex++; + + if (!can_batch_texture(facep)) + { //face is bump mapped or has an animated texture matrix -- can't + //batch more than 1 texture at a time + break; + } + + if (cur_tex >= texture_index_channels) + { //cut batches when index channels are depleted + break; + } + + tex = facep->getTexture(); + + texture_list.push_back(tex); } - if (!can_batch_texture(facep)) - { //face is bump mapped or has an animated texture matrix -- can't - //batch more than 1 texture at a time + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big break; } - if (cur_tex >= texture_index_channels) - { //cut batches when index channels are depleted - break; - } + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); - tex = facep->getTexture(); - - texture_list.push_back(tex); + facep->setTextureIndex(cur_tex); } + } + + tex = texture_list[0]; + } + else + { + while (i != faces.end() && + (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) + { + facep = *i; + + + //face has no texture index + facep->mDrawInfo = NULL; + facep->setTextureIndex(255); if (geom_count + facep->getGeomCount() > max_vertices) { //cut batches on geom count too big @@ -4094,69 +4240,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: ++i; index_count += facep->getIndicesCount(); geom_count += facep->getGeomCount(); - - facep->setTextureIndex(cur_tex); } } - - tex = texture_list[0]; } - else - { - while (i != faces.end() && - (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) - { - facep = *i; - - //face has no texture index - facep->mDrawInfo = NULL; - facep->setTextureIndex(255); - - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut batches on geom count too big - break; - } - - ++i; - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); - } - } - - //create/delete/resize vertex buffer if needed + //create vertex buffer LLVertexBuffer* buffer = NULL; - { //try to find a buffer to reuse - LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter); - - if (found_iter != group->mBufferMap[mask].end()) - { - if ((U32) buffer_index < found_iter->second.size()) - { - buffer = found_iter->second[buffer_index]; - } - } - } - - if (!buffer || !buffer->isWriteable()) - { //create new buffer if needed + { + LLFastTimer t(FTM_GEN_DRAW_INFO_ALLOCATE); buffer = createVertexBuffer(mask, buffer_usage); buffer->allocateBuffer(geom_count, index_count, TRUE); } - else - { //resize pre-existing buffer - if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != buffer_usage || - buffer->getTypeMask() != mask) - { - buffer = createVertexBuffer(mask, buffer_usage); - buffer->allocateBuffer(geom_count, index_count, TRUE); - } - else - { - buffer->resizeBuffer(geom_count, index_count); - } - } group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize(); @@ -4190,10 +4285,22 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: LLVOVolume* vobj = drawablep->getVOVolume(); LLVolume* volume = vobj->getVolume(); + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } + U32 te_idx = facep->getTEOffset(); + llassert(!facep->isState(LLFace::RIGGED)); + facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset); + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true); + + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(false); + } } } @@ -4244,7 +4351,6 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } } else if (gPipeline.canUseVertexShaders() - && group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD && LLPipeline::sRenderBump && te->getShiny()) { //shiny @@ -4357,6 +4463,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun mFaceList.clear(); //for each drawable + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; @@ -4377,17 +4484,21 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun //sum up face verts and indices drawablep->updateFaceSize(i); LLFace* facep = drawablep->getFace(i); - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) + if (facep) { - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); - llassert(facep->getIndicesCount() < 65536); - //remember face (for sorting) - mFaceList.push_back(facep); - } - else - { - facep->clearVertexBuffer(); + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA && + facep->getGeomCount() + vertex_count <= 65536) + { + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + //remember face (for sorting) + mFaceList.push_back(facep); + } + else + { + facep->clearVertexBuffer(); + } } } } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index b4c08b797..cc7b5cf10 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -81,7 +81,7 @@ public: virtual bool isVolumeGlobal() const = 0; // Are we in global space? virtual bool isActive() const = 0; // Is this object currently active? virtual const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const = 0; - virtual void updateRelativeXform() = 0; + virtual void updateRelativeXform(bool force_identity = false) = 0; virtual U32 getID() const = 0; virtual void preRebuild() = 0; }; @@ -203,7 +203,7 @@ public: LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status); - void updateRelativeXform(); + void updateRelativeXform(bool force_identity = false); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ void updateFaceSize(S32 idx); /*virtual*/ BOOL updateLOD(); diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 6614a97d8..05e033392 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -151,6 +151,10 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) drawable->addFace(poolp, NULL); } face = drawable->getFace(0); + if (!face) + { + return TRUE; + } // LLVector2 uvs[4]; // LLVector3 vtx[4]; @@ -166,7 +170,8 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) static const unsigned int indices_per_quad = 6; static const LLCachedControl render_transparent_water("RenderTransparentWater",false); - const S32 size = (render_transparent_water && !LLGLSLShader::sNoFixedFunction) ? 16 : 1; + static const LLCachedControl water_subdiv("SianaVoidWaterSubdivision", 16); + const S32 size = (render_transparent_water && LLGLSLShader::sNoFixedFunction) ? water_subdiv : 1; const S32 num_quads = size * size; face->setSize(vertices_per_quad * num_quads, indices_per_quad * num_quads); diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index 5f7c79786..4da0c0ade 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -2,62 +2,82 @@ * @file llwearable.cpp * @brief LLWearable class implementation * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" -#include "imageids.h" -#include "llassetstorage.h" -#include "lldbstrings.h" -#include "lldir.h" -#include "llquantize.h" - #include "llagent.h" #include "llagentcamera.h" #include "llagentwearables.h" #include "lldictionary.h" -#include "llnotificationsutil.h" -#include "llassetuploadresponders.h" -#include "llviewerwindow.h" #include "llfloatercustomize.h" -#include "llinventoryobserver.h" +#include "lllocaltextureobject.h" +#include "llnotificationsutil.h" #include "llviewertexturelist.h" -#include "llviewerinventory.h" +#include "llinventorymodel.h" +#include "llinventoryobserver.h" +#include "lltexlayer.h" +#include "lltexglobalcolor.h" +#include "lltrans.h" #include "llviewerregion.h" +#include "llvisualparam.h" +#include "llvoavatar.h" #include "llvoavatarself.h" +#include "llvoavatardefines.h" #include "llwearable.h" +#include "llviewercontrol.h" using namespace LLVOAvatarDefines; // static S32 LLWearable::sCurrentDefinitionVersion = 1; +// support class - remove for 2.1 (hackity hack hack) +class LLOverrideBakedTextureUpdate +{ +public: + LLOverrideBakedTextureUpdate(bool temp_state) + { + U32 num_bakes = (U32) LLVOAvatarDefines::BAKED_NUM_INDICES; + for( U32 index = 0; index < num_bakes; ++index ) + { + composite_enabled[index] = gAgentAvatarp->isCompositeUpdateEnabled(index); + } + gAgentAvatarp->setCompositeUpdatesEnabled(temp_state); + } + + ~LLOverrideBakedTextureUpdate() + { + U32 num_bakes = (U32)LLVOAvatarDefines::BAKED_NUM_INDICES; + for( U32 index = 0; index < num_bakes; ++index ) + { + gAgentAvatarp->setCompositeUpdatesEnabled(index, composite_enabled[index]); + } + } +private: + bool composite_enabled[LLVOAvatarDefines::BAKED_NUM_INDICES]; +}; + // Private local functions static std::string terse_F32_to_string(F32 f); static std::string asset_id_to_filename(const LLUUID &asset_id); @@ -106,14 +126,14 @@ BOOL LLWearable::FileExportParams( FILE* file ) fprintf( file, "type %d\n", type ); // parameters - S32 num_parameters = mVisualParamMap.size(); + S32 num_parameters = mVisualParamIndexMap.size(); fprintf( file, "parameters %d\n", num_parameters ); - for (param_map_t::iterator iter = mVisualParamMap.begin(); - iter != mVisualParamMap.end(); ++iter) + for (visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); + iter != mVisualParamIndexMap.end(); ++iter) { S32 param_id = iter->first; - F32 param_weight = iter->second; + F32 param_weight = iter->second->getWeight(); fprintf( file, "%d %s\n", param_id, terse_F32_to_string(param_weight).c_str() ); } @@ -135,8 +155,7 @@ BOOL LLWearable::FileExportTextures( FILE* file ) iter != mTEMap.end(); ++iter) { S32 te = iter->first; - LLUUID& image_id = iter->second; - fprintf( file, "%d %s\n", te, image_id.asString().c_str() ); + fprintf( file, "%d %s\n", te, iter->second->getID().asString().c_str() ); } return TRUE; @@ -182,17 +201,19 @@ BOOL LLWearable::exportFile(LLFILE* file) const } // parameters - S32 num_parameters = mVisualParamMap.size(); + S32 num_parameters = mVisualParamIndexMap.size(); if( fprintf( file, "parameters %d\n", num_parameters ) < 0 ) { return FALSE; } - for (param_map_t::const_iterator iter = mVisualParamMap.begin(); - iter != mVisualParamMap.end(); ++iter) + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); + iter != mVisualParamIndexMap.end(); + ++iter) { S32 param_id = iter->first; - F32 param_weight = iter->second; + const LLVisualParam* param = iter->second; + F32 param_weight = param->getWeight(); if( fprintf( file, "%d %s\n", param_id, terse_F32_to_string( param_weight ).c_str() ) < 0 ) { return FALSE; @@ -206,11 +227,10 @@ BOOL LLWearable::exportFile(LLFILE* file) const return FALSE; } - for (te_map_t::const_iterator iter = mTEMap.begin(); - iter != mTEMap.end(); ++iter) + for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter) { S32 te = iter->first; - const LLUUID& image_id = iter->second; + const LLUUID& image_id = iter->second->getID(); if( fprintf( file, "%d %s\n", te, image_id.asString().c_str()) < 0 ) { return FALSE; @@ -220,6 +240,38 @@ BOOL LLWearable::exportFile(LLFILE* file) const } +void LLWearable::createVisualParams() +{ + for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam()) + { + if (param->getWearableType() == mType) + { + addVisualParam(param->cloneParam(this)); + } + } + + // resync driver parameters to point to the newly cloned driven parameters + for (visual_param_index_map_t::iterator param_iter = mVisualParamIndexMap.begin(); + param_iter != mVisualParamIndexMap.end(); + ++param_iter) + { + LLVisualParam* param = param_iter->second; + LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam; + // need this line to disambiguate between versions of LLCharacter::getVisualParam() + LLVisualParam*(LLVOAvatarSelf::*avatar_function)(S32)const = &LLVOAvatarSelf::getVisualParam; + param->resetDrivenParams(); + if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) + { + if( !param->linkDrivenParams(boost::bind(avatar_function,gAgentAvatarp.get(),_1 ), true)) + { + llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl; + continue; + } + } + } +} BOOL LLWearable::importFile( LLFILE* file ) { @@ -229,6 +281,10 @@ BOOL LLWearable::importFile( LLFILE* file ) char text_buffer[2048]; /* Flawfinder: ignore */ S32 fields_read = 0; + // suppress texlayerset updates while wearables are being imported. Layersets will be updated + // when the wearables are "worn", not loaded. Note state will be restored when this object is destroyed. + LLOverrideBakedTextureUpdate stop_bakes(false); + // read header and version fields_read = fscanf( file, "LLWearable version %d\n", &mDefinitionVersion ); if( fields_read != 1 ) @@ -240,7 +296,13 @@ BOOL LLWearable::importFile( LLFILE* file ) return FALSE; } - if( mDefinitionVersion > LLWearable::sCurrentDefinitionVersion ) + + // Temoprary hack to allow wearables with definition version 24 to still load. + // This should only affect lindens and NDA'd testers who have saved wearables in 2.0 + // the extra check for version == 24 can be removed before release, once internal testers + // have loaded these wearables again. See hack pt 2 at bottom of function to ensure that + // these wearables get re-saved with version definition 22. + if( mDefinitionVersion > LLWearable::sCurrentDefinitionVersion && mDefinitionVersion != 24 ) { llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl; return FALSE; @@ -361,6 +423,11 @@ BOOL LLWearable::importFile( LLFILE* file ) return FALSE; } + if( num_parameters != mVisualParamIndexMap.size() ) + { + llwarns << "Wearable parameter mismatch. Reading in " << num_parameters << " from file, but created " << mVisualParamIndexMap.size() << " from avatar parameters. type: " << mType << llendl; + } + // parameters S32 i; for( i = 0; i < num_parameters; i++ ) @@ -373,7 +440,7 @@ BOOL LLWearable::importFile( LLFILE* file ) llwarns << "Bad Wearable asset: bad parameter, #" << i << llendl; return FALSE; } - mVisualParamMap[param_id] = param_weight; + mSavedVisualParamMap[param_id] = param_weight; } // textures header @@ -404,10 +471,30 @@ BOOL LLWearable::importFile( LLFILE* file ) llwarns << "Bad Wearable asset: bad texture uuid: " << text_buffer << llendl; return FALSE; } + LLUUID id = LLUUID(text_buffer); + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( id ); + if( mTEMap.find(te) != mTEMap.end() ) + { + delete mTEMap[te]; + } + if( mSavedTEMap.find(te) != mSavedTEMap.end() ) + { + delete mSavedTEMap[te]; + } - mTEMap[te] = LLUUID(text_buffer ); + if(gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) + { + image->setLoadedCallback(LLVOAvatarSelf::debugOnTimingLocalTexLoaded,0,TRUE,FALSE, new LLVOAvatarSelf::LLAvatarTexData(id, (LLVOAvatarDefines::ETextureIndex)te), NULL); + } + LLUUID textureid(text_buffer); + mTEMap[te] = new LLLocalTextureObject(image, textureid); + mSavedTEMap[te] = new LLLocalTextureObject(image, textureid); + createLayers(te); } + // copy all saved param values to working params + revertValues(); + return TRUE; } @@ -435,16 +522,16 @@ BOOL LLWearable::isOldVersion() const param; param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) { - if( (param->getWearableType() == mType) && (param->isTweakable()) ) + if( (param->getWearableType() == mType) && (param->isTweakable() ) ) { param_count++; - if( !is_in_map(mVisualParamMap, param->getID() ) ) + if( !is_in_map(mVisualParamIndexMap, param->getID() ) ) { return TRUE; } } } - if( param_count != mVisualParamMap.size() ) + if( param_count != mVisualParamIndexMap.size() ) { return TRUE; } @@ -485,60 +572,21 @@ BOOL LLWearable::isDirty() const param; param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) { - if( (param->getWearableType() == mType) && (param->isTweakable()) ) + if( (param->getWearableType() == mType) + && (param->isTweakable() ) + && !param->getCrossWearable()) { - F32 weight = get_if_there(mVisualParamMap, param->getID(), param->getDefaultWeight()); - weight = llclamp( weight, param->getMinWeight(), param->getMaxWeight() ); + F32 current_weight = getVisualParamWeight(param->getID()); + current_weight = llclamp( current_weight, param->getMinWeight(), param->getMaxWeight() ); + F32 saved_weight = get_if_there(mSavedVisualParamMap, param->getID(), param->getDefaultWeight()); + saved_weight = llclamp( saved_weight, param->getMinWeight(), param->getMaxWeight() ); - U8 a = F32_to_U8( param->getWeight(), param->getMinWeight(), param->getMaxWeight() ); + U8 a = F32_to_U8( saved_weight, param->getMinWeight(), param->getMaxWeight() ); + U8 b = F32_to_U8( current_weight, param->getMinWeight(), param->getMaxWeight() ); - if(gAgentAvatarp->getAppearanceFlag() == true) - { - //boob - if(param->getID() == 507) - { - weight = get_if_there(mVisualParamMap, param->getID(), gAgentAvatarp->getActualBoobGrav()); - weight = llclamp( weight, param->getMinWeight(), param->getMaxWeight() ); - } - /*//butt - if(param->getID() == 795) - { - weight = get_if_there(mVisualParamMap, param->getID(), avatar->getActualButtGrav()); - weight = llclamp( weight, param->getMinWeight(), param->getMaxWeight() ); - } - //fat - if(param->getID() == 157) - { - weight = get_if_there(mVisualParamMap, param->getID(), avatar->getActualFatGrav()); - weight = llclamp( weight, param->getMinWeight(), param->getMaxWeight() ); - } - */ - } - else - { - //boob - if(param->getID() == 507) - { - a = F32_to_U8( gAgentAvatarp->getActualBoobGrav(), param->getMinWeight(), param->getMaxWeight() ); - } - /*//butt - if(param->getID() == 795) - { - a = F32_to_U8( gAgentAvatarp->getActualButtGrav(), param->getMinWeight(), param->getMaxWeight() ); - } - //fat - if(param->getID() == 157) - { - a = F32_to_U8( gAgentAvatarp->getActualFatGrav(), param->getMinWeight(), param->getMaxWeight() ); - } - */ - } - - - U8 b = F32_to_U8( weight, param->getMinWeight(), param->getMaxWeight() ); if( a != b ) { - llwarns << "param ID " << param->getID() << " was changed." << llendl; + //llwarns << "param ID " << param->getID() << " was changed." << llendl; return TRUE; } } @@ -546,31 +594,31 @@ BOOL LLWearable::isDirty() const for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if( LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te ) == mType ) + if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) { - LLViewerTexture* avatar_image = gAgentAvatarp->getTEImage( te ); - if( !avatar_image ) + te_map_t::const_iterator current_iter = mTEMap.find(te); + if(current_iter != mTEMap.end()) { - llassert( 0 ); - continue; - } - const LLUUID& image_id = get_if_there(mTEMap, te, LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te ) ); - if( avatar_image->getID() != image_id ) - { - llwarns << "image ID " << avatar_image->getID() << " was changed." << llendl; - return TRUE; + const LLUUID& current_image_id = current_iter->second->getID(); + te_map_t::const_iterator saved_iter = mSavedTEMap.find(te); + if(saved_iter != mSavedTEMap.end()) + { + const LLUUID& saved_image_id = saved_iter->second->getID(); + if (saved_image_id != current_image_id) + { + // saved vs current images are different, wearable is dirty + return TRUE; + } + } + else + { + // image found in current image list but not saved image list + return TRUE; + } } } } - //if( gFloaterCustomize ) - //{ - // if( mDescription != gFloaterCustomize->getWearableDescription( mType ) ) - // { - // return TRUE; - // } - //} - return FALSE; } @@ -579,30 +627,41 @@ void LLWearable::setParamsToDefaults() { if (!isAgentAvatarValid()) return; - mVisualParamMap.clear(); for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) { - if( (((LLViewerVisualParam*)param)->getWearableType() == mType ) && (param->isTweakable()) ) + if( (((LLViewerVisualParam*)param)->getWearableType() == mType ) && (param->isTweakable() ) ) { - mVisualParamMap[param->getID()] = param->getDefaultWeight(); + setVisualParamWeight(param->getID(),param->getDefaultWeight(), FALSE); } } } void LLWearable::setTexturesToDefaults() { - mTEMap.clear(); for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) { - mTEMap[te] = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); + LLUUID id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); + LLViewerFetchedTexture * image = LLViewerTextureManager::getFetchedTexture( id ); + if( mTEMap.find(te) == mTEMap.end() ) + { + mTEMap[te] = new LLLocalTextureObject(image, id); + createLayers(te); + } + else + { + // Local Texture Object already created, just set image and UUID + LLLocalTextureObject *lto = mTEMap[te]; + lto->setID(id); + lto->setImage(image); + } } } } // Updates the user's avatar's appearance -void LLWearable::writeToAvatar( BOOL set_by_user ) +void LLWearable::writeToAvatar() { if (!isAgentAvatarValid()) return; @@ -611,84 +670,46 @@ void LLWearable::writeToAvatar( BOOL set_by_user ) // Pull params for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) { - if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (param->isTweakable()) ) + // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the + // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way. + if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (!((LLViewerVisualParam*)param)->getCrossWearable()) ) { S32 param_id = param->getID(); - F32 weight = get_if_there(mVisualParamMap, param_id, param->getDefaultWeight()); + F32 weight = getVisualParamWeight(param_id); - //ZOMG: When switching shapes from inventory - if(param_id == 507) - gAgentAvatarp->setActualBoobGrav(weight); - /*if(param_id == 795) - gAgentAvatarp->setActualButtGrav(weight); - if(param_id == 157) - gAgentAvatarp->setActualFatGrav(weight); - */ - - // only animate with user-originated changes - if (set_by_user) - { - param->setAnimationTarget(weight, set_by_user); - } - else - { - gAgentAvatarp->setVisualParamWeight( param_id, weight, set_by_user ); - } + gAgentAvatarp->setVisualParamWeight( param_id, weight, FALSE ); } } - // only interpolate with user-originated changes - if (set_by_user) - { - gAgentAvatarp->startAppearanceAnimation(TRUE, TRUE); - } - // Pull texture entries for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) { - const LLUUID& image_id = get_if_there(mTEMap, te, LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te ) ); - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id ); - gAgentAvatarp->setLocTexTE( te, image, set_by_user ); - } - } - - gAgentAvatarp->updateVisualParams(); - - if( gFloaterCustomize ) - { - LLViewerInventoryItem* item; - item = (LLViewerInventoryItem*)gInventory.getItem(gAgentWearables.getWearableItemID(mType, 0)); // TODO: MULTI-WEARABLE - U32 perm_mask = PERM_NONE; - BOOL is_complete = FALSE; - if(item) - { - perm_mask = item->getPermissions().getMaskOwner(); - is_complete = item->isComplete(); - if(!is_complete) + te_map_t::const_iterator iter = mTEMap.find(te); + LLUUID image_id; + if(iter != mTEMap.end()) { - item->fetchFromServer(); + image_id = iter->second->getID(); } + else + { + image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); + } + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); + // MULTI-WEARABLE: assume index 0 will be used when writing to avatar. TODO: eliminate the need for this. + gAgentAvatarp->setLocalTextureTE(te, image, 0); } - gFloaterCustomize->setWearable(mType, this, perm_mask, is_complete); - LLFloaterCustomize::setCurrentWearableType( mType ); } ESex new_sex = gAgentAvatarp->getSex(); if( old_sex != new_sex ) { - gAgentAvatarp->updateSexDependentLayerSets( set_by_user ); + gAgentAvatarp->updateSexDependentLayerSets( FALSE ); } - - gAgentAvatarp->updateMeshTextures(); - -// if( set_by_user ) -// { -// gAgent.sendAgentSetAppearance(); -// } } + // Updates the user's avatar's appearance, replacing this wearables' parameters and textures with default values. // static void LLWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ) @@ -714,19 +735,9 @@ void LLWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload_bake } } - // Pull textures - LLViewerTexture* image =LLViewerTextureManager::getFetchedTexture( IMG_DEFAULT_AVATAR ); - for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + if(gAgentCamera.cameraCustomizeAvatar()) { - if( LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te ) == type ) - { - gAgentAvatarp->setLocTexTE( te, image, upload_bake ); - } - } - - if( gFloaterCustomize ) - { - gFloaterCustomize->setWearable(type, NULL, PERM_ALL, TRUE); + gFloaterCustomize->wearablesChanged(type); } gAgentAvatarp->updateVisualParams(); @@ -740,7 +751,7 @@ void LLWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload_bake // Does not copy mAssetID. // Definition version is current: removes obsolete enties and creates default values for new ones. -void LLWearable::copyDataFrom( LLWearable* src ) +void LLWearable::copyDataFrom(const LLWearable* src) { if (!isAgentAvatarValid()) return; @@ -750,51 +761,55 @@ void LLWearable::copyDataFrom( LLWearable* src ) mDescription = src->mDescription; mPermissions = src->mPermissions; mSaleInfo = src->mSaleInfo; + setType(src->mType); + mSavedVisualParamMap.clear(); // Deep copy of mVisualParamMap (copies only those params that are current, filling in defaults where needed) - for( LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); + for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); param; param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) { - if( (param->getWearableType() == mType) && (param->isTweakable()) ) + if( (param->getWearableType() == mType) ) { S32 id = param->getID(); - F32 weight = get_if_there(src->mVisualParamMap, id, param->getDefaultWeight() ); - //llwarns << "------------------------------" << llendl; - //llwarns << "copydatafrom" << llendl; - //llwarns << "------------------------------" << llendl; - - //if(id == 507) - //{ - // llwarns << "weight = " << weight << llendl; - // llwarns << "actual = " << avatar->getActualBoobGrav() << llendl; - // llwarns << "mVisualParamMap[id] = " << mVisualParamMap[id] << llendl; - //} - - //pretty sure right - if(id == 507) - gAgentAvatarp->setActualBoobGrav(weight); - /*if(id == 795) - gAgentAvatarp->setActualButtGrav(weight); - if(id == 157) - gAgentAvatarp->setActualFatGrav(weight); - */ - - - mVisualParamMap[id] = weight; + F32 weight = src->getVisualParamWeight(id); + mSavedVisualParamMap[id] = weight; } } + destroyTextures(); // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if( LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te ) == mType ) + if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) { - const LLUUID& image_id = get_if_there(src->mTEMap, te, LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te ) ); - mTEMap[te] = image_id; + te_map_t::const_iterator iter = src->mTEMap.find(te); + LLUUID image_id; + LLViewerFetchedTexture *image = NULL; + if(iter != src->mTEMap.end()) + { + image = src->getLocalTextureObject(te)->getImage(); + image_id = src->getLocalTextureObject(te)->getID(); + mTEMap[te] = new LLLocalTextureObject(image, image_id); + mSavedTEMap[te] = new LLLocalTextureObject(image, image_id); + mTEMap[te]->setBakedReady(src->getLocalTextureObject(te)->getBakedReady()); + mTEMap[te]->setDiscard(src->getLocalTextureObject(te)->getDiscard()); + } + else + { + image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); + image = LLViewerTextureManager::getFetchedTexture( image_id ); + mTEMap[te] = new LLLocalTextureObject(image, image_id); + mSavedTEMap[te] = new LLLocalTextureObject(image, image_id); + } + createLayers(te); } } + + // Probably reduntant, but ensure that the newly created wearable is not dirty by setting current value of params in new wearable + // to be the same as the saved values (which were loaded from src at param->cloneParam(this)) + revertValues(); } void LLWearable::setItemID(const LLUUID& item_id) @@ -806,13 +821,329 @@ const LLUUID& LLWearable::getItemID() const { return mItemID; } + void LLWearable::setType(LLWearableType::EType type) { mType = type; + createVisualParams(); } -// Updates asset from the user's avatar -void LLWearable::readFromAvatar() +LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) +{ + te_map_t::iterator iter = mTEMap.find(index); + if( iter != mTEMap.end() ) + { + LLLocalTextureObject* lto = iter->second; + return lto; + } + return NULL; +} + +const LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const +{ + te_map_t::const_iterator iter = mTEMap.find(index); + if( iter != mTEMap.end() ) + { + const LLLocalTextureObject* lto = iter->second; + return lto; + } + return NULL; +} + +void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject <o) +{ + if( mTEMap.find(index) != mTEMap.end() ) + { + mTEMap.erase(index); + } + mTEMap[index] = new LLLocalTextureObject(lto); +} + + +void LLWearable::addVisualParam(LLVisualParam *param) +{ + if( mVisualParamIndexMap[param->getID()] ) + { + delete mVisualParamIndexMap[param->getID()]; + } + param->setIsDummy(FALSE); + mVisualParamIndexMap[param->getID()] = param; + mSavedVisualParamMap[param->getID()] = param->getDefaultWeight(); +} + +void LLWearable::setVisualParams() +{ + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++) + { + S32 id = iter->first; + LLVisualParam *wearable_param = iter->second; + F32 value = wearable_param->getWeight(); + gAgentAvatarp->setVisualParamWeight(id, value, FALSE); + } +} + + +void LLWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL upload_bake) +{ + if( is_in_map(mVisualParamIndexMap, param_index ) ) + { + LLVisualParam *wearable_param = mVisualParamIndexMap[param_index]; + wearable_param->setWeight(value, upload_bake); + } + else + { + llerrs << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl; + } +} + +F32 LLWearable::getVisualParamWeight(S32 param_index) const +{ + if( is_in_map(mVisualParamIndexMap, param_index ) ) + { + const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second; + return wearable_param->getWeight(); + } + else + { + llwarns << "LLWerable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl; + } + return (F32)-1.0; +} + +LLVisualParam* LLWearable::getVisualParam(S32 index) const +{ + visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(index); + return (iter == mVisualParamIndexMap.end()) ? NULL : iter->second; +} + + +void LLWearable::getVisualParams(visual_param_vec_t &list) +{ + visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); + visual_param_index_map_t::iterator end = mVisualParamIndexMap.end(); + + // add all visual params to the passed-in vector + for( ; iter != end; ++iter ) + { + list.push_back(iter->second); + } +} + +void LLWearable::animateParams(F32 delta, BOOL upload_bake) +{ + for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); + iter != mVisualParamIndexMap.end(); + ++iter) + { + LLVisualParam *param = (LLVisualParam*) iter->second; + param->animate(delta, upload_bake); + } +} + +LLColor4 LLWearable::getClothesColor(S32 te) const +{ + LLColor4 color; + U32 param_name[3]; + if( LLVOAvatar::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) ) + { + for( U8 index = 0; index < 3; index++ ) + { + color.mV[index] = getVisualParamWeight(param_name[index]); + } + } + return color; +} + +void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ) +{ + U32 param_name[3]; + if( LLVOAvatar::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) ) + { + for( U8 index = 0; index < 3; index++ ) + { + setVisualParamWeight(param_name[index], new_color.mV[index], upload_bake); + } + } +} + +void LLWearable::revertValues() +{ + //update saved settings so wearable is no longer dirty + // non-driver params first + for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) + { + S32 id = iter->first; + F32 value = iter->second; + LLVisualParam *param = getVisualParam(id); + if(param && !dynamic_cast(param) ) + { + setVisualParamWeight(id, value, TRUE); + } + } + + //then driver params + for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) + { + S32 id = iter->first; + F32 value = iter->second; + LLVisualParam *param = getVisualParam(id); + if(param && dynamic_cast(param) ) + { + setVisualParamWeight(id, value, TRUE); + } + } + + // make sure that saved values are sane + for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) + { + S32 id = iter->first; + LLVisualParam *param = getVisualParam(id); + if( param ) + { + mSavedVisualParamMap[id] = param->getWeight(); + } + } + + syncImages(mSavedTEMap, mTEMap); + + + /*LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); + if( panel ) + { + panel->updateScrollingPanelList(); + }*/ + if( gFloaterCustomize && gAgentWearables.getWearableIndex(this)==0 ) + gFloaterCustomize->updateScrollingPanelList(); + +} + +BOOL LLWearable::isOnTop() const +{ + return (this == gAgentWearables.getTopWearable(mType)); +} + +void LLWearable::createLayers(S32 te) +{ + LLTexLayerSet *layer_set = gAgentAvatarp->getLayerSet((ETextureIndex)te); + if (layer_set) + { + layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this); + } + else + { + llerrs << "could not find layerset for LTO in wearable!" << llendl; + } +} + +void LLWearable::saveValues() +{ + //update saved settings so wearable is no longer dirty + mSavedVisualParamMap.clear(); + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) + { + S32 id = iter->first; + LLVisualParam *wearable_param = iter->second; + F32 value = wearable_param->getWeight(); + mSavedVisualParamMap[id] = value; + } + + // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) + syncImages(mTEMap, mSavedTEMap); + + + /*LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); + if( panel ) + { + panel->updateScrollingPanelList(); + }*/ + + if( gFloaterCustomize && gAgentWearables.getWearableIndex(this)==0) + gFloaterCustomize->updateScrollingPanelList(); +} + +void LLWearable::syncImages(te_map_t &src, te_map_t &dst) +{ + // Deep copy of src (copies only those tes that are current, filling in defaults where needed) + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + { + if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + te_map_t::const_iterator iter = src.find(te); + LLUUID image_id; + LLViewerFetchedTexture *image = NULL; + LLLocalTextureObject *lto = NULL; + if(iter != src.end()) + { + // there's a Local Texture Object in the source image map. Use this to populate the values to store in the destination image map. + lto = iter->second; + image = lto->getImage(); + image_id = lto->getID(); + } + else + { + // there is no Local Texture Object in the source image map. Get defaults values for populating the destination image map. + image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); + image = LLViewerTextureManager::getFetchedTexture( image_id ); + } + + if( dst.find(te) != dst.end() ) + { + // there's already an entry in the destination map for the texture. Just update its values. + dst[te]->setImage(image); + dst[te]->setID(image_id); + } + else + { + // no entry found in the destination map, we need to create a new Local Texture Object + dst[te] = new LLLocalTextureObject(image, image_id); + } + + if( lto ) + { + // If we pulled values from a Local Texture Object in the source map, make sure the proper flags are set in the new (or updated) entry in the destination map. + dst[te]->setBakedReady(lto->getBakedReady()); + dst[te]->setDiscard(lto->getDiscard()); + } + } + } +} + +void LLWearable::destroyTextures() +{ + for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter ) + { + LLLocalTextureObject *lto = iter->second; + delete lto; + } + mTEMap.clear(); + for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter ) + { + LLLocalTextureObject *lto = iter->second; + delete lto; + } + mSavedTEMap.clear(); +} + +void LLWearable::pullCrossWearableValues() +{ + // scan through all of the avatar's visual parameters + for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam()) + { + if( param ) + { + LLDriverParam *driver_param = dynamic_cast(param); + if(driver_param) + { + // parameter is a driver parameter, have it update its + driver_param->updateCrossDrivenParams(getType()); + } + } + } +} + +/*void LLWearable::readFromAvatar() { LLVOAvatar* avatar = gAgentAvatarp; llassert( avatar ); @@ -828,22 +1159,6 @@ void LLWearable::readFromAvatar() { if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (param->isTweakable()) ) { - - //pretty sure is right - if(param->getID() == 507) - avatar->setActualBoobGrav(param->getWeight()); - /*if(param->getID() == 151) - avatar->setActualButtGrav(param->getWeight()); - if(param->getID() == 157) - avatar->setActualFatGrav(param->getWeight()); - */ - //if(param->getID() == 507) - //{ - // llwarns << "current = " << avatar->getActualBoobGrav() << llendl; - // llwarns << "param weight = " << param->getWeight() << llendl; - //} - - mVisualParamMap[param->getID()] = param->getWeight(); } } @@ -865,7 +1180,7 @@ void LLWearable::readFromAvatar() //{ // mDescription = gFloaterCustomize->getWearableDescription( mType ); //} -} +}*/ void LLWearable::setLabelUpdated() const @@ -925,7 +1240,7 @@ void LLWearable::saveNewAsset() const { llinfos << "Update Agent Inventory via capability" << llendl; LLSD body; - body["folder_id"] = gInventory.findCategoryUUIDForType(getAssetType()); + body["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetToFolderType(getAssetType())); body["asset_type"] = LLAssetType::lookup(getAssetType()); body["inventory_type"] = LLInventoryType::lookup(LLInventoryType::IT_WEARABLE); body["name"] = getName(); @@ -969,31 +1284,24 @@ void LLWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userda // delete the context data delete data; -} -BOOL LLWearable::isMatchedToInventoryItem( LLViewerInventoryItem* item ) -{ - return - ( mName == item->getName() ) && - ( mDescription == item->getDescription() ) && - ( mPermissions == item->getPermissions() ) && - ( mSaleInfo == item->getSaleInfo() ); } std::ostream& operator<<(std::ostream &s, const LLWearable &w) { - s << "wearable " << LLWearableType::getTypeName( w.mType ) << "\n"; + s << "wearable " << LLWearableType::getTypeName(w.mType) << "\n"; s << " Name: " << w.mName << "\n"; s << " Desc: " << w.mDescription << "\n"; //w.mPermissions //w.mSaleInfo s << " Params:" << "\n"; - for (LLWearable::param_map_t::const_iterator iter = w.mVisualParamMap.begin(); - iter != w.mVisualParamMap.end(); ++iter) + for (LLWearable::visual_param_index_map_t::const_iterator iter = w.mVisualParamIndexMap.begin(); + iter != w.mVisualParamIndexMap.end(); ++iter) { S32 param_id = iter->first; - F32 param_weight = iter->second; + LLVisualParam *wearable_param = iter->second; + F32 param_weight = wearable_param->getWeight(); s << " " << param_id << " " << param_weight << "\n"; } @@ -1002,14 +1310,14 @@ std::ostream& operator<<(std::ostream &s, const LLWearable &w) iter != w.mTEMap.end(); ++iter) { S32 te = iter->first; - const LLUUID& image_id = iter->second; + const LLUUID& image_id = iter->second->getID(); s << " " << te << " " << image_id << "\n"; } return s; } -std::string terse_F32_to_string( F32 f ) +std::string terse_F32_to_string(F32 f) { std::string r = llformat("%.2f", f); S32 len = r.length(); diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h index 1459f4f6a..af9119d6d 100644 --- a/indra/newview/llwearable.h +++ b/indra/newview/llwearable.h @@ -2,31 +2,25 @@ * @file llwearable.h * @brief LLWearable class header file * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -39,8 +33,13 @@ #include "llsaleinfo.h" #include "llassetstorage.h" #include "llwearabletype.h" +#include "llfile.h" +#include "lllocaltextureobject.h" class LLViewerInventoryItem; +class LLVisualParam; +class LLTexGlobalColorInfo; +class LLTexGlobalColor; class LLWearable { @@ -50,7 +49,7 @@ class LLWearable // Constructors and destructors //-------------------------------------------------------------------- private: - // Private constructor used by LLWearableList + // Private constructors used by LLWearableList LLWearable(const LLTransactionID& transactionID); LLWearable(const LLAssetID& assetID); public: @@ -73,22 +72,24 @@ public: const std::string& getName() const { return mName; } void setName( const std::string& name ) { mName = name; } const std::string& getDescription() const { return mDescription; } - void setDescription( const std::string& desc ) { mDescription = desc; } + void setDescription(const std::string& desc) { mDescription = desc; } const LLPermissions& getPermissions() const { return mPermissions; } - void setPermissions( const LLPermissions& p ) { mPermissions = p; } + void setPermissions(const LLPermissions& p) { mPermissions = p; } const LLSaleInfo& getSaleInfo() const { return mSaleInfo; } - - - void setSaleInfo( const LLSaleInfo& info ) { mSaleInfo = info; } + void setSaleInfo(const LLSaleInfo& info) { mSaleInfo = info; } const std::string& getTypeLabel() const; const std::string& getTypeName() const; LLAssetType::EType getAssetType() const; + S32 getDefinitionVersion() const { return mDefinitionVersion; } + void setDefinitionVersion( S32 new_version ) { mDefinitionVersion = new_version; } + +public: + typedef std::vector visual_param_vec_t; BOOL isDirty() const; BOOL isOldVersion() const; - void writeToAvatar( BOOL set_by_user ); - void readFromAvatar(); + void writeToAvatar(); void removeFromAvatar( BOOL upload_bake ) { LLWearable::removeFromAvatar( mType, upload_bake ); } static void removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ); @@ -101,15 +102,34 @@ public: void saveNewAsset() const; static void onSaveNewAssetComplete( const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status ); - BOOL isMatchedToInventoryItem( LLViewerInventoryItem* item ); - - void copyDataFrom( LLWearable* src ); + void copyDataFrom(const LLWearable* src); static void setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; } friend std::ostream& operator<<(std::ostream &s, const LLWearable &w); void setItemID(const LLUUID& item_id); + LLLocalTextureObject* getLocalTextureObject(S32 index); + const LLLocalTextureObject* getLocalTextureObject(S32 index) const; + + void setLocalTextureObject(S32 index, LLLocalTextureObject <o); + void addVisualParam(LLVisualParam *param); + void setVisualParams(); + void setVisualParamWeight(S32 index, F32 value, BOOL upload_bake); + F32 getVisualParamWeight(S32 index) const; + LLVisualParam* getVisualParam(S32 index) const; + void getVisualParams(visual_param_vec_t &list); + void animateParams(F32 delta, BOOL upload_bake); + + LLColor4 getClothesColor(S32 te) const; + void setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ); + + void revertValues(); + void saveValues(); + void pullCrossWearableValues(); + + BOOL isOnTop() const; + // Something happened that requires the wearable's label to be updated (e.g. worn/unworn). void setLabelUpdated() const; @@ -118,7 +138,13 @@ public: void refreshName(); private: - typedef std::map te_map_t; + typedef std::map te_map_t; + typedef std::map visual_param_index_map_t; + + void createLayers(S32 te); + void createVisualParams(); + void syncImages(te_map_t &src, te_map_t &dst); + void destroyTextures(); static S32 sCurrentDefinitionVersion; // Depends on the current state of the avatar_lad.xml. S32 mDefinitionVersion; // Depends on the state of the avatar_lad.xml when this asset was created. @@ -131,9 +157,12 @@ private: LLWearableType::EType mType; typedef std::map param_map_t; - param_map_t mVisualParamMap; // maps visual param id to weight - - te_map_t mTEMap; // maps TE to Image ID + param_map_t mSavedVisualParamMap; // last saved version of visual params + + visual_param_index_map_t mVisualParamIndexMap; + + te_map_t mTEMap; // maps TE to LocalTextureObject + te_map_t mSavedTEMap; // last saved version of TEMap LLUUID mItemID; // ID of the inventory item in the agent's inventory }; diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index 2648b537a..ed81936f7 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -2,31 +2,25 @@ * @file llwearablelist.cpp * @brief LLWearableList class implementation * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,10 +32,10 @@ #include "llassetstorage.h" #include "llagent.h" #include "llvoavatar.h" -#include "llviewerinventory.h" -//#include "llfloaterchat.h" #include "llviewerstats.h" #include "llnotificationsutil.h" +#include "llinventorymodel.h" +#include "lltrans.h" // Callback struct struct LLWearableArrivedData @@ -64,8 +58,6 @@ struct LLWearableArrivedData S32 mRetries; }; - - //////////////////////////////////////////////////////////////////////////// // LLWearableList @@ -80,7 +72,7 @@ void LLWearableList::cleanup() mList.clear(); } -void LLWearableList::getAsset( const LLAssetID& assetID, const std::string& wearable_name, LLAssetType::EType asset_type, void(*asset_arrived_callback)(LLWearable*, void* userdata), void* userdata ) +void LLWearableList::getAsset(const LLAssetID& assetID, const std::string& wearable_name, LLAssetType::EType asset_type, void(*asset_arrived_callback)(LLWearable*, void* userdata), void* userdata) { llassert( (asset_type == LLAssetType::AT_CLOTHING) || (asset_type == LLAssetType::AT_BODYPART) ); LLWearable* instance = get_if_there(mList, assetID, (LLWearable*)NULL ); @@ -212,46 +204,7 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID } -// Creates a new wearable just like the old_wearable but with data copied over from item -LLWearable* LLWearableList::createWearableMatchedToInventoryItem( LLWearable* old_wearable, LLViewerInventoryItem* item ) -{ - lldebugs << "LLWearableList::createWearableMatchedToInventoryItem()" << llendl; - - LLWearable* wearable = generateNewWearable(); - wearable->copyDataFrom( old_wearable ); - - wearable->setName( item->getName() ); - wearable->setDescription( item->getDescription() ); - wearable->setPermissions( item->getPermissions() ); - wearable->setSaleInfo( item->getSaleInfo() ); - - // Send to the dataserver - wearable->saveNewAsset(); - - return wearable; -} - -LLWearable* LLWearableList::createCopyFromAvatar( LLWearable* old_wearable, const std::string& new_name ) -{ - lldebugs << "LLWearableList::createCopyFromAvatar()" << llendl; - - LLWearable* wearable = generateNewWearable(); - wearable->copyDataFrom( old_wearable ); - LLPermissions perm(old_wearable->getPermissions()); - perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), LLUUID::null, true); - wearable->setPermissions(perm); - wearable->readFromAvatar(); // update from the avatar - - if (!new_name.empty()) wearable->setName(new_name); - - // Send to the dataserver - wearable->saveNewAsset(); - - return wearable; -} - - -LLWearable* LLWearableList::createCopy( LLWearable* old_wearable ) +LLWearable* LLWearableList::createCopy(const LLWearable* old_wearable, const std::string& new_name) { lldebugs << "LLWearableList::createCopy()" << llendl; @@ -262,6 +215,7 @@ LLWearable* LLWearableList::createCopy( LLWearable* old_wearable ) perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), LLUUID::null, true); wearable->setPermissions(perm); + if (!new_name.empty()) wearable->setName(new_name); // Send to the dataserver wearable->saveNewAsset(); @@ -276,8 +230,7 @@ LLWearable* LLWearableList::createNewWearable( LLWearableType::EType type ) LLWearable *wearable = generateNewWearable(); wearable->setType( type ); - std::string name = "New "; - name.append( wearable->getTypeLabel() ); + std::string name = LLWearableType::getTypeDefaultNewName(wearable->getType()); wearable->setName( name ); LLPermissions perm; @@ -289,6 +242,9 @@ LLWearable* LLWearableList::createNewWearable( LLWearableType::EType type ) wearable->setParamsToDefaults(); wearable->setTexturesToDefaults(); + //mark all values (params & images) as saved + wearable->saveValues(); + // Send to the dataserver wearable->saveNewAsset(); diff --git a/indra/newview/llwearablelist.h b/indra/newview/llwearablelist.h index 6f64549ae..12d0037ae 100644 --- a/indra/newview/llwearablelist.h +++ b/indra/newview/llwearablelist.h @@ -2,31 +2,25 @@ * @file llwearablelist.h * @brief LLWearableList class header file * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -52,7 +46,7 @@ public: ~LLWearableList(); void cleanup() ; - S32 getLength() { return mList.size(); } + S32 getLength() const { return mList.size(); } void getAsset(const LLAssetID& assetID, const std::string& wearable_name, @@ -60,10 +54,8 @@ public: void(*asset_arrived_callback)(LLWearable*, void* userdata), void* userdata); - LLWearable* createWearableMatchedToInventoryItem( LLWearable* old_wearable, LLViewerInventoryItem* item ); - LLWearable* createCopyFromAvatar( LLWearable* old_wearable, const std::string& new_name = std::string() ); - LLWearable* createCopy( LLWearable* old_wearable ); - LLWearable* createNewWearable( LLWearableType::EType type ); + LLWearable* createCopy(const LLWearable* old_wearable, const std::string& new_name = std::string()); + LLWearable* createNewWearable(LLWearableType::EType type); // Callback static void processGetAssetReply(const char* filename, const LLAssetID& assetID, void* user_data, S32 status, LLExtStat ext_status); diff --git a/indra/newview/llwearabletype.cpp b/indra/newview/llwearabletype.cpp index 18507f262..66ac79a12 100644 --- a/indra/newview/llwearabletype.cpp +++ b/indra/newview/llwearabletype.cpp @@ -26,6 +26,7 @@ #include "llviewerprecompiledheaders.h" #include "llwearabletype.h" +#include "llinventoryfunctions.h" #include "lltrans.h" struct WearableEntry : public LLDictionaryEntry @@ -39,6 +40,7 @@ struct WearableEntry : public LLDictionaryEntry LLDictionaryEntry(name), mAssetType(assetType), mDefaultNewName(default_new_name), + //*TODO:Translate mLabel(/*LLTrans::getString*/(name)), mIconName(iconName), mDisableCameraSwitch(disable_camera_switch), @@ -59,6 +61,12 @@ class LLWearableDictionary : public LLSingleton, { public: LLWearableDictionary(); + +// [RLVa:KB] - Checked: 2010-03-03 (RLVa-1.2.0a) | Added: RLVa-1.2.0a +protected: + // The default implementation asserts on 'notFound()' and returns -1 which isn't a valid EWearableType + virtual LLWearableType::EType notFound() const { return LLWearableType::WT_INVALID; } +// [/RLVa:KB] }; LLWearableDictionary::LLWearableDictionary() @@ -150,9 +158,9 @@ BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type) // static BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type) { - return false; //Disabled - /*const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); + const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); const WearableEntry *entry = dict->lookup(type); if (!entry) return FALSE; - return entry->mAllowMultiwear;*/ + return entry->mAllowMultiwear; } + diff --git a/indra/newview/llwearabletype.h b/indra/newview/llwearabletype.h index 6e6115b69..d633b4807 100644 --- a/indra/newview/llwearabletype.h +++ b/indra/newview/llwearabletype.h @@ -37,23 +37,23 @@ class LLWearableType public: enum EType { - WT_SHAPE = 0, - WT_SKIN = 1, - WT_HAIR = 2, - WT_EYES = 3, - WT_SHIRT = 4, - WT_PANTS = 5, - WT_SHOES = 6, - WT_SOCKS = 7, - WT_JACKET = 8, - WT_GLOVES = 9, + WT_SHAPE = 0, + WT_SKIN = 1, + WT_HAIR = 2, + WT_EYES = 3, + WT_SHIRT = 4, + WT_PANTS = 5, + WT_SHOES = 6, + WT_SOCKS = 7, + WT_JACKET = 8, + WT_GLOVES = 9, WT_UNDERSHIRT = 10, WT_UNDERPANTS = 11, - WT_SKIRT = 12, - WT_ALPHA = 13, - WT_TATTOO = 14, - WT_PHYSICS = 15, - WT_COUNT = 16, + WT_SKIRT = 12, + WT_ALPHA = 13, + WT_TATTOO = 14, + WT_PHYSICS = 15, + WT_COUNT = 16, WT_INVALID = 255, WT_NONE = -1, @@ -73,5 +73,4 @@ protected: ~LLWearableType() {} }; - #endif // LL_LLWEARABLETYPE_H diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp index 5c7ee642d..9b6ae853f 100644 --- a/indra/newview/llwindebug.cpp +++ b/indra/newview/llwindebug.cpp @@ -690,31 +690,6 @@ LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter( return gFilterFunc; } -BOOL PreventSetUnhandledExceptionFilter() -{ - HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll")); - if (hKernel32 == NULL) - return FALSE; - - void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter"); - if(pOrgEntry == NULL) - return FALSE; - - unsigned char newJump[ 100 ]; - DWORD dwOrgEntryAddr = (DWORD)pOrgEntry; - dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far - void *pNewFunc = &MyDummySetUnhandledExceptionFilter; - DWORD dwNewEntryAddr = (DWORD) pNewFunc; - DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr; - - newJump[ 0 ] = 0xE9; // JMP absolute - memcpy(&newJump[ 1 ], &dwRelativeAddr, sizeof(pNewFunc)); - SIZE_T bytesWritten; - BOOL bRet = WriteProcessMemory(GetCurrentProcess(), - pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten); - return bRet; -} - // static void LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) { @@ -765,9 +740,6 @@ void LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; prev_filter = SetUnhandledExceptionFilter(filter_func); - // *REMOVE:Mani - //PreventSetUnhandledExceptionFilter(); - if(prev_filter != gFilterFunc) { LL_WARNS("AppInit") diff --git a/indra/newview/llwldaycycle.cpp b/indra/newview/llwldaycycle.cpp index 61222520b..d6383d311 100644 --- a/indra/newview/llwldaycycle.cpp +++ b/indra/newview/llwldaycycle.cpp @@ -80,7 +80,7 @@ void LLWLDayCycle::loadDayCycle(const LLSD& day_data, LLWLParamKey::EScope scope // alert the user LLSD args; args["SKY"] = day_data[i][1].asString(); - LLNotificationsUtil::add("WLMissingSky", args, LLSD()); + LLNotifications::instance().add("WLMissingSky", args, LLSD()); continue; } } @@ -161,13 +161,13 @@ LLSD LLWLDayCycle::asLLSD() bool LLWLDayCycle::getSkyRefs(std::map& refs) const { bool result = true; - LLWLParamManager* wl_mgr = LLWLParamManager::getInstance(); + LLWLParamManager& wl_mgr = LLWLParamManager::instance(); refs.clear(); for (std::map::const_iterator iter = mTimeMap.begin(); iter != mTimeMap.end(); ++iter) { const LLWLParamKey& key = iter->second; - if (!wl_mgr->getParamSet(key, refs[key])) + if (!wl_mgr.getParamSet(key, refs[key])) { llwarns << "Cannot find sky [" << key.name << "] referenced by a day cycle" << llendl; result = false; diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp index 2c245480a..0495d9c51 100644 --- a/indra/newview/llwlhandlers.cpp +++ b/indra/newview/llwlhandlers.cpp @@ -37,7 +37,7 @@ #include "llagent.h" #include "llviewerregion.h" #include "llenvmanager.h" -#include "llnotifications.h" +#include "llnotificationsutil.h" /**** * LLEnvironmentRequest @@ -144,7 +144,7 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content) { LLSD args(LLSD::emptyMap()); args["WAIT"] = (F64)UPDATE_WAIT_SECONDS; - LLNotifications::instance().add("EnvUpdateRate", args); + LLNotificationsUtil::add("EnvUpdateRate", args); return false; } @@ -186,7 +186,7 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content) LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings! Reason from sim: " << content["fail_reason"].asString() << LL_ENDL; LLSD args(LLSD::emptyMap()); args["FAIL_REASON"] = content["fail_reason"].asString(); - LLNotifications::instance().add("WLRegionApplyFail", args); + LLNotificationsUtil::add("WLRegionApplyFail", args); LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false); } } @@ -199,5 +199,5 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content) LLSD args(LLSD::emptyMap()); args["FAIL_REASON"] = msg.str(); - LLNotifications::instance().add("WLRegionApplyFail", args); + LLNotificationsUtil::add("WLRegionApplyFail", args); } diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index 7845165b3..a87487f55 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -80,6 +80,10 @@ #include "curl/curl.h" #include "llstreamtools.h" +// [RLVa:KB] - Checked: 2011-09-04 (RLVa-1.4.1a) | Added: RLVa-1.4.1a +#include +// [/RLVa:KB] + LLWLParamManager::LLWLParamManager() : //set the defaults for the controls @@ -722,6 +726,18 @@ void LLWLParamManager::getPresetNames(preset_name_list_t& region, preset_name_li } } +// [RLVa:KB] - Checked: 2011-09-04 (RLVa-1.4.1a) | Added: RLVa-1.4.1a +const std::string& LLWLParamManager::findPreset(const std::string& strPresetName, LLEnvKey::EScope eScope) +{ + for (std::map::const_iterator itList = mParamList.begin(); itList != mParamList.end(); itList++) + { + const LLWLParamKey& wlKey = itList->first; + if ( (wlKey.scope == eScope) && (boost::iequals(wlKey.name, strPresetName)) ) + return wlKey.name; + } + return LLStringUtil::null; +} +// [/RLVa:KB] void LLWLParamManager::getUserPresetNames(preset_name_list_t& user) const { preset_name_list_t region, sys; // unused diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h index 62df522cf..c65cbcb36 100644 --- a/indra/newview/llwlparammanager.h +++ b/indra/newview/llwlparammanager.h @@ -227,6 +227,10 @@ public: /// @return user and system preset names as a single list void getPresetNames(preset_name_list_t& region, preset_name_list_t& user, preset_name_list_t& sys) const; +// [RLVa:KB] - Checked: 2011-09-04 (RLVa-1.4.1a) | Added: RLVa-1.4.1a + const std::string& findPreset(const std::string& strPresetName, LLEnvKey::EScope eScope); +// [/RLVa:KB] + /// @return user preset names void getUserPresetNames(preset_name_list_t& user) const; diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 97d1977c8..6f92bedf9 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -200,9 +200,11 @@ LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) } //Classic clouds +#if ENABLE_CLASSIC_CLOUDS regionp->mCloudLayer.create(regionp); regionp->mCloudLayer.setWidth((F32)mWidth); regionp->mCloudLayer.setWindPointer(®ionp->mWind); +#endif mRegionList.push_back(regionp); mActiveRegionList.push_back(regionp); @@ -682,6 +684,7 @@ void LLWorld::updateParticles() LLViewerPartSim::getInstance()->updateSimulation(); } +#if ENABLE_CLASSIC_CLOUDS void LLWorld::updateClouds(const F32 dt) { static const LLCachedControl freeze_time("FreezeTime",false); @@ -740,6 +743,7 @@ LLCloudGroup* LLWorld::findCloudGroup(const LLCloudPuff &puff) } return NULL; } +#endif void LLWorld::renderPropertyLines() @@ -1486,6 +1490,11 @@ void LLWorld::getAvatars(std::vector* avatar_ids, std::vector gHTTPRegistrationEstablishAgentCommunication( diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index ba9663596..a9b3f3b53 100644 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -124,8 +124,10 @@ public: void updateRegions(F32 max_update_time); void updateVisibilities(); void updateParticles(); +#if ENABLE_CLASSIC_CLOUDS void updateClouds(const F32 dt); LLCloudGroup * findCloudGroup(const LLCloudPuff &puff); +#endif void renderPropertyLines(); @@ -163,6 +165,11 @@ public: std::vector* positions = NULL, const LLVector3d& relative_to = LLVector3d(), F32 radius = FLT_MAX) const; + // Returns 'true' if the region is in mRegionList, + // 'false' if the region has been removed due to region change + // or if the circuit to this simulator had been lost. + bool isRegionListed(const LLViewerRegion* region) const; + private: region_list_t mActiveRegionList; region_list_t mRegionList; diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h index c40963b3c..97c79dddf 100644 --- a/indra/newview/llworldmapview.h +++ b/indra/newview/llworldmapview.h @@ -52,7 +52,6 @@ const S32 DEFAULT_TRACKING_ARROW_SIZE = 16; class LLColor4; class LLColor4U; -class LLCoordGL; class LLViewerTexture; class LLTextBox; diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 159255078..af5e977b2 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -469,7 +469,7 @@ void LLXMLRPCTransaction::Impl::setCurlStatus(CURLcode code) case CURLE_SSL_CACERT: case CURLE_SSL_CONNECT_ERROR: message = - "Often this means that your computer\'s clock is set incorrectly.\n" + "Often this means that your computer's clock is set incorrectly.\n" "Please go to Control Panels and make sure the time and date\n" "are set correctly.\n" "\n" diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 0472606f1..bd2424294 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -111,6 +111,7 @@ // [RLVa:KB] #include "rlvhandler.h" +#include "rlvlocks.h" // [/RLVa:KB] void check_stack_depth(S32 stack_depth) @@ -221,6 +222,7 @@ std::string gPoolNames[] = void drawBox(const LLVector3& c, const LLVector3& r); void drawBoxOutline(const LLVector3& pos, const LLVector3& size); U32 nhpo2(U32 v); +LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage); glh::matrix4f glh_copy_matrix(F32* src) { @@ -359,9 +361,11 @@ LLPipeline::LLPipeline() : mInitialized(FALSE), mVertexShadersEnabled(FALSE), mVertexShadersLoaded(0), + mTransformFeedbackPrimitives(0), mRenderDebugFeatureMask(0), mRenderDebugMask(0), mOldRenderDebugMask(0), + mMeshDirtyQueryObject(0), mGroupQ1Locked(false), mGroupQ2Locked(false), mResetVertexBuffers(false), @@ -396,7 +400,7 @@ void LLPipeline::init() sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("ShyotlRenderUseStreamVBO"); - LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO"); + LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO") && gSavedSettings.getBOOL("VertexShaderEnable"); //Temporary workaround for vaos being broken when shaders are off LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw"); sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); @@ -449,15 +453,24 @@ void LLPipeline::init() mSpotLightFade[i] = 1.f; } - mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0); - mDeferredVB->allocateBuffer(8, 0, true); + if (mCubeVB.isNull()) + { + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + if(mDeferredVB.isNull()) + { + mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0); + mDeferredVB->allocateBuffer(8, 0, true); + } setLightingDetail(-1); gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("RenderUseFarClip")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("RenderAvatarMaxVisible")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); //gSavedSettings.getControl("RenderDelayVBUpdate")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); - + gSavedSettings.getControl("UseOcclusion")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); + gSavedSettings.getControl("VertexShaderEnable")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); + gSavedSettings.getControl("RenderFSAASamples")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); } LLPipeline::~LLPipeline() @@ -561,6 +574,12 @@ void LLPipeline::destroyGL() sDelayedVBOEnable = 30; LLVertexBuffer::sEnableVBOs = FALSE; } + + } + if (mMeshDirtyQueryObject) + { + glDeleteQueriesARB(1, &mMeshDirtyQueryObject); + mMeshDirtyQueryObject = 0; } } @@ -717,9 +736,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (shadow_detail > 0) { //allocate 4 sun shadow maps + U32 sun_shadow_map_width = ((U32(resX*scale)+1)&~1); // must be even to avoid a stripe in the horizontal shadow blur for (U32 i = 0; i < 4; i++) { - if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; + if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; } } else @@ -735,9 +755,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (shadow_detail > 1) { //allocate two spot shadow maps + U32 spot_shadow_map_width = width; for (U32 i = 4; i < 6; i++) { - if (!mShadow[i].allocate(width, height, 0, TRUE, FALSE)) return false; + if (!mShadow[i].allocate(spot_shadow_map_width, height, 0, TRUE, FALSE)) return false; } } else @@ -823,6 +844,7 @@ void LLPipeline::refreshCachedSettings() LLPipeline::sUseOcclusion = (!gUseWireframe + && LLGLSLShader::sNoFixedFunction && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; @@ -834,25 +856,21 @@ void LLPipeline::releaseGLBuffers() if (mNoiseMap) { - LLImageGL::deleteTextures(1, &mNoiseMap); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 0, 1, &mNoiseMap); mNoiseMap = 0; } if (mTrueNoiseMap) { - LLImageGL::deleteTextures(1, &mTrueNoiseMap); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 0, 1, &mTrueNoiseMap); mTrueNoiseMap = 0; } - if (mLightFunc) - { - LLImageGL::deleteTextures(1, &mLightFunc); - mLightFunc = 0; - } + releaseLUTBuffers(); mWaterRef.release(); mWaterDis.release(); - + for (U32 i = 0; i < 3; i++) { mGlow[i].release(); @@ -864,6 +882,15 @@ void LLPipeline::releaseGLBuffers() LLVOAvatar::resetImpostors(); } +void LLPipeline::releaseLUTBuffers() +{ + if (mLightFunc) + { + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_R8, 0, 1, &mLightFunc); + mLightFunc = 0; + } +} + void LLPipeline::releaseScreenBuffers() { mScreen.release(); @@ -934,7 +961,7 @@ void LLPipeline::createGLBuffers() noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; } - LLImageGL::generateTextures(1, &mNoiseMap); + LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 1, &mNoiseMap); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); @@ -950,56 +977,74 @@ void LLPipeline::createGLBuffers() noise[i] = ll_frand()*2.0-1.0; } - LLImageGL::generateTextures(1, &mTrueNoiseMap); + LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 1, &mTrueNoiseMap); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } - if (!mLightFunc) - { - U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); - U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); - U8* lg = new U8[lightResX*lightResY]; - - for (U32 y = 0; y < lightResY; ++y) - { - for (U32 x = 0; x < lightResX; ++x) - { - //spec func - F32 sa = (F32) x/(lightResX-1); - F32 spec = (F32) y/(lightResY-1); - //lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255); - - //F32 sp = acosf(sa)/(1.f-spec); - - static const LLCachedControl render_specular_exponent("RenderSpecularExponent"); - sa = powf(sa, render_specular_exponent); - F32 a = acosf(sa*0.25f+0.75f); - F32 m = llmax(0.5f-spec*0.5f, 0.001f); - F32 t2 = tanf(a)/m; - t2 *= t2; - - F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f; - F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2); - - lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255); - } - } - - LLImageGL::generateTextures(1, &mLightFunc); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, lg, false); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); - - delete [] lg; - } + createLUTBuffers(); } gBumpImageList.restoreGL(); } +void LLPipeline::createLUTBuffers() +{ + if (sRenderDeferred) + { + if (!mLightFunc) + { + U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); + U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); + U8* ls = new U8[lightResX*lightResY]; + static const LLCachedControl specExp("RenderSpecularExponent"); + // Calculate the (normalized) Blinn-Phong specular lookup texture. + for (U32 y = 0; y < lightResY; ++y) + { + for (U32 x = 0; x < lightResX; ++x) + { + ls[y*lightResX+x] = 0; + F32 sa = (F32) x/(lightResX-1); + F32 spec = (F32) y/(lightResY-1); + F32 n = spec * spec * specExp; + + // Nothing special here. Just your typical blinn-phong term. + spec = powf(sa, n); + + // Apply our normalization function. + // Note: This is the full equation that applies the full normalization curve, not an approximation. + // This is fine, given we only need to create our LUT once per buffer initialization. + // The only trade off is we have a really low dynamic range. + // This means we have to account for things not being able to exceed 0 to 1 in our shaders. + spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n))); + + // Always sample at a 1.0/2.2 curve. + // This "Gamma corrects" our specular term, boosting our lower exponent reflections. + spec = powf(spec, 1.f/2.2f); + + // Easy fix for our dynamic range problem: divide by 6 here, multiply by 6 in our shaders. + // This allows for our specular term to exceed a value of 1 in our shaders. + // This is something that can be important for energy conserving specular models where higher exponents can result in highlights that exceed a range of 0 to 1. + // Technically, we could just use an R16F texture, but driver support for R16F textures can be somewhat spotty at times. + // This works remarkably well for higher specular exponents, though banding can sometimes be seen on lower exponents. + // Combined with a bit of noise and trilinear filtering, the banding is hardly noticable. + ls[y*lightResX+x] = (U8)(llclamp(spec * (1.f / 6), 0.f, 1.f) * 255); + } + } + + LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_R8, 1, &mLightFunc); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls, false); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + + delete [] ls; + } + } +} + + void LLPipeline::restoreGL() { LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_RESTORE_GL); @@ -1605,6 +1650,16 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) if (done) { drawablep->clearState(LLDrawable::ON_MOVE_LIST); + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { //will likely not receive any future world matrix updates + // -- this keeps attachments from getting stuck in space and falling off your avatar + drawablep->clearState(LLDrawable::ANIMATED_CHILD); + markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, TRUE); + if (drawablep->getVObj()) + { + drawablep->getVObj()->dirtySpatialGroup(TRUE); + } + } iter = moved_list.erase(curiter); } } @@ -2000,8 +2055,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl gGLLastMatrix = NULL; gGL.loadMatrix(gGLLastModelView); - - LLVertexBuffer::unbind(); LLGLDisable blend(GL_BLEND); LLGLDisable test(GL_ALPHA_TEST); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -2045,7 +2098,16 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl { //if no shader is currently bound, use the occlusion shader instead of fixed function if we can // (shadow render uses a special shader that clamps to clip planes) bound_shader = true; - gOcclusionProgram.bind(); + gOcclusionCubeProgram.bind(); + } + + if (sUseOcclusion > 1) + { + if (mCubeVB.isNull()) + { //cube VB will be used for issuing occlusion queries + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); } for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); @@ -2077,7 +2139,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl if (bound_shader) { - gOcclusionProgram.unbind(); + gOcclusionCubeProgram.unbind(); } camera.disableUserClipPlane(); @@ -2117,10 +2179,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl { mScreen.flush(); } - /*else if (LLPipeline::sUseOcclusion > 1) - { - glFlush(); - }*/ } void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) @@ -2189,7 +2247,7 @@ void LLPipeline::markOccluder(LLSpatialGroup* group) void LLPipeline::doOcclusion(LLCamera& camera) { - if (LLPipeline::sUseOcclusion > 1 && sCull->hasOcclusionGroups()) + if (LLGLSLShader::sNoFixedFunction && LLPipeline::sUseOcclusion > 1 && sCull->hasOcclusionGroups()) { LLVertexBuffer::unbind(); @@ -2214,14 +2272,20 @@ void LLPipeline::doOcclusion(LLCamera& camera) { if (LLPipeline::sShadowRender) { - gDeferredShadowProgram.bind(); + gDeferredShadowCubeProgram.bind(); } else { - gOcclusionProgram.bind(); + gOcclusionCubeProgram.bind(); } } + if (mCubeVB.isNull()) + { //cube VB will be used for issuing occlusion queries + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) { LLSpatialGroup* group = *iter; @@ -2233,11 +2297,11 @@ void LLPipeline::doOcclusion(LLCamera& camera) { if (LLPipeline::sShadowRender) { - gDeferredShadowProgram.unbind(); + gDeferredShadowCubeProgram.unbind(); } else { - gOcclusionProgram.unbind(); + gOcclusionCubeProgram.unbind(); } } @@ -2256,6 +2320,8 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) return update_complete; } +static LLFastTimer::DeclareTimer FTM_SEED_VBO_POOLS("Seed VBO Pool"); + void LLPipeline::updateGL() { while (!LLGLUpdate::sGLQ.empty()) @@ -2265,6 +2331,11 @@ void LLPipeline::updateGL() glu->mInQ = FALSE; LLGLUpdate::sGLQ.pop_front(); } + + /*{ //seed VBO Pools + LLFastTimer t(FTM_SEED_VBO_POOLS); + LLVertexBuffer::seedPools(); + }*/ } void LLPipeline::rebuildPriorityGroups() @@ -2642,11 +2713,16 @@ void LLPipeline::processPartitionQ() mPartitionQ.clear(); } + +void LLPipeline::markMeshDirty(LLSpatialGroup* group) +{ + mMeshDirtyGroup.push_back(group); +} + void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) { LLMemType mt(LLMemType::MTYPE_PIPELINE); - //llassert(is_main_thread()); - + if (group && !group->isDead() && group->mSpatialPartition) { if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD) @@ -3013,7 +3089,11 @@ void renderScriptedBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3040,7 +3120,11 @@ void renderScriptedTouchBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3066,7 +3150,11 @@ void renderPhysicalBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3092,7 +3180,11 @@ void renderParticleBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3110,7 +3202,11 @@ void renderSoundHighlights(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3140,45 +3236,20 @@ void LLPipeline::postSort(LLCamera& camera) //rebuild groups sCull->assertDrawMapsEmpty(); - /*LLSpatialGroup::sNoDelete = FALSE; - for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) - { - LLSpatialGroup* group = *i; - if (sUseOcclusion && - group->isState(LLSpatialGroup::OCCLUDED)) - { - continue; - } - - group->rebuildGeom(); - } - LLSpatialGroup::sNoDelete = TRUE;*/ - - rebuildPriorityGroups(); llpushcallstacks ; - const S32 bin_count = 1024*8; - - static LLCullResult::drawinfo_list_t alpha_bins[bin_count]; - static U32 bin_size[bin_count]; - - //clear one bin per frame to avoid memory bloat - static S32 clear_idx = 0; - clear_idx = (1+clear_idx)%bin_count; - alpha_bins[clear_idx].clear(); - - for (U32 j = 0; j < bin_count; j++) - { - bin_size[j] = 0; - } - + //build render map for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { LLSpatialGroup* group = *i; + + static LLCachedControl RenderAutoHideSurfaceAreaLimit("RenderAutoHideSurfaceAreaLimit", 0.f); if (sUseOcclusion && - group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + group->isOcclusionState(LLSpatialGroup::OCCLUDED) || + (RenderAutoHideSurfaceAreaLimit > 0.f && + group->mSurfaceArea > RenderAutoHideSurfaceAreaLimit*llmax(group->mObjectBoxSize, 10.f))) { continue; } @@ -3242,14 +3313,44 @@ void LLPipeline::postSort(LLCamera& camera) } } } + + //flush particle VB + LLVOPartGroup::sVB->flush(); + + /*bool use_transform_feedback = gTransformPositionProgram.mProgramObject && !mMeshDirtyGroup.empty(); + + if (use_transform_feedback) + { //place a query around potential transform feedback code for synchronization + mTransformFeedbackPrimitives = 0; + + if (!mMeshDirtyQueryObject) + { + glGenQueriesARB(1, &mMeshDirtyQueryObject); + } + + glBeginQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mMeshDirtyQueryObject); + }*/ + + //pack vertex buffers for groups that chose to delay their updates + for (LLSpatialGroup::sg_vector_t::iterator iter = mMeshDirtyGroup.begin(); iter != mMeshDirtyGroup.end(); ++iter) + { + (*iter)->rebuildMesh(); + } + + /*if (use_transform_feedback) + }*/ + + mMeshDirtyGroup.clear(); + if (!sShadowRender) { std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater()); } + llpushcallstacks ; - forAllVisibleDrawables(updateParticleActivity); + forAllVisibleDrawables(updateParticleActivity); //for llfloateravatarlist // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus static const LLCachedControl beacons_visible("BeaconsVisible", false); @@ -3347,7 +3448,11 @@ void LLPipeline::postSort(LLCamera& camera) { if (object->mDrawable) { - gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te)); + LLFace * facep = object->mDrawable->getFace(te); + if (facep) + { + gPipeline.mSelectedFaces.push_back(facep); + } } return true; } @@ -5968,7 +6073,6 @@ LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj) return NULL; } - void LLPipeline::resetVertexBuffers(LLDrawable* drawable) { if (!drawable) @@ -5979,13 +6083,15 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable) for (S32 i = 0; i < drawable->getNumFaces(); i++) { LLFace* facep = drawable->getFace(i); - facep->clearVertexBuffer(); + if (facep) + { + facep->clearVertexBuffer(); + } } } void LLPipeline::resetVertexBuffers() -{ - mResetVertexBuffers = true; +{ mResetVertexBuffers = true; } void LLPipeline::doResetVertexBuffers() @@ -5994,9 +6100,12 @@ void LLPipeline::doResetVertexBuffers() { return; } - + mResetVertexBuffers = false; + mCubeVB = NULL; + mDeferredVB = NULL; + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { @@ -6015,11 +6124,14 @@ void LLPipeline::doResetVertexBuffers() gSky.resetVertexBuffers(); + LLVOPartGroup::destroyGL(); + LLVertexBuffer::cleanupClass(); //delete all name pool caches LLGLNamePool::cleanupPools(); + if (LLVertexBuffer::sGLCount > 0) { llwarns << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << llendl; @@ -6029,15 +6141,17 @@ void LLPipeline::doResetVertexBuffers() sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("ShyotlRenderUseStreamVBO"); - LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO"); + LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO") && gPipeline.canUseVertexShaders(); //Temporary workaround for vaos being broken when shaders are off LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw"); LLVertexBuffer::sEnableVBOs = gSavedSettings.getBOOL("RenderVBOEnable"); - LLVertexBuffer::sDisableVBOMapping = LLVertexBuffer::sEnableVBOs && gSavedSettings.getBOOL("RenderVBOMappingDisable") ; + LLVertexBuffer::sDisableVBOMapping = LLVertexBuffer::sEnableVBOs;// && gSavedSettings.getBOOL("RenderVBOMappingDisable") ; //Temporary workaround for vbo mapping being straight up broken sBakeSunlight = gSavedSettings.getBOOL("RenderBakeSunlight"); sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha"); LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind"); LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping); + + LLVOPartGroup::restoreGL(); } void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture, BOOL batch_texture) @@ -7130,6 +7244,11 @@ void LLPipeline::renderDeferredLighting() glh::matrix4f mat = glh_copy_matrix(gGLModelView); + if(mDeferredVB.isNull()) + { + mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0); + mDeferredVB->allocateBuffer(8, 0, true); + } LLStrider vert; mDeferredVB->getVertexStrider(vert); LLStrider tc0; @@ -7342,12 +7461,17 @@ void LLPipeline::renderDeferredLighting() std::list light_colors; LLVertexBuffer::unbind(); - LLVector4a* v = (LLVector4a*) vert.get(); { bindDeferredShader(gDeferredLightProgram); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + if (mCubeVB.isNull()) + { + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) { @@ -7393,25 +7517,7 @@ void LLPipeline::renderDeferredLighting() } sVisibleLightCount++; - - glh::vec3f tc(c); - mat.mult_matrix_vec(tc); - - //vertex positions are encoded so the 3 bits of their vertex index - //correspond to their axis facing, with bit position 3,2,1 matching - //axis facing x,y,z, bit set meaning positive facing, bit clear - //meaning negative facing - mDeferredVB->getVertexStrider(vert); - v[0].set(c[0]-s,c[1]-s,c[2]-s); // 0 - 0000 - v[1].set(c[0]-s,c[1]-s,c[2]+s); // 1 - 0001 - v[2].set(c[0]-s,c[1]+s,c[2]-s); // 2 - 0010 - v[3].set(c[0]-s,c[1]+s,c[2]+s); // 3 - 0011 - - v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100 - v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101 - v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110 - v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111 - + if (camera->getOrigin().mV[0] > c[0] + s + 0.2f || camera->getOrigin().mV[0] < c[0] - s - 0.2f || camera->getOrigin().mV[1] > c[1] + s + 0.2f || @@ -7429,16 +7535,13 @@ void LLPipeline::renderDeferredLighting() } LLFastTimer ftm(FTM_LOCAL_LIGHTS); - //glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); - gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); + gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); - //gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); gGL.syncMatrices(); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center)); + + mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); stop_glerror(); } } @@ -7451,6 +7554,9 @@ void LLPipeline::renderDeferredLighting() continue; } + glh::vec3f tc(c); + mat.mult_matrix_vec(tc); + fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s)); light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); } @@ -7463,7 +7569,7 @@ void LLPipeline::renderDeferredLighting() LLGLDepthTest depth(GL_TRUE, GL_FALSE); bindDeferredShader(gDeferredSpotLightProgram); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); @@ -7481,36 +7587,17 @@ void LLPipeline::renderDeferredLighting() sVisibleLightCount++; - glh::vec3f tc(c); - mat.mult_matrix_vec(tc); - setupSpotLight(gDeferredSpotLightProgram, drawablep); LLColor3 col = volume->getLightColor(); - - //vertex positions are encoded so the 3 bits of their vertex index - //correspond to their axis facing, with bit position 3,2,1 matching - //axis facing x,y,z, bit set meaning positive facing, bit clear - //meaning negative facing - mDeferredVB->getVertexStrider(vert); - v[0].set(c[0]-s,c[1]-s,c[2]-s); // 0 - 0000 - v[1].set(c[0]-s,c[1]-s,c[2]+s); // 1 - 0001 - v[2].set(c[0]-s,c[1]+s,c[2]-s); // 2 - 0010 - v[3].set(c[0]-s,c[1]+s,c[2]+s); // 3 - 0011 - - v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100 - v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101 - v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110 - v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111 - gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); + gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); gGL.syncMatrices(); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center)); + + mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); } gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION); unbindDeferredShader(gDeferredSpotLightProgram); @@ -7542,8 +7629,6 @@ void LLPipeline::renderDeferredLighting() LLVector4 light[max_count]; LLVector4 col[max_count]; -// glVertexPointer(2, GL_FLOAT, 0, vert); - F32 far_z = 0.f; while (!fullscreen_lights.empty()) @@ -7981,7 +8066,11 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) gPipeline.pushRenderTypeMask(); if (detail < 4) { +#if ENABLE_CLASSIC_CLOUDS clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS, END_RENDER_TYPES); +#else + clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES); +#endif if (detail < 3) { clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); @@ -8038,7 +8127,9 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) { clearRenderTypeMask(LLPipeline::RENDER_TYPE_GROUND, LLPipeline::RENDER_TYPE_SKY, +#if ENABLE_CLASSIC_CLOUDS LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS, +#endif LLPipeline::RENDER_TYPE_WL_CLOUDS, LLPipeline::RENDER_TYPE_WL_SKY, END_RENDER_TYPES); @@ -8172,7 +8263,7 @@ static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows"); static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow"); static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow"); -void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion) +void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion, U32 target_width) { LLFastTimer t(FTM_SHADOW_RENDER); @@ -8196,7 +8287,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera if (use_shader) { - gDeferredShadowProgram.bind(); + gDeferredShadowCubeProgram.bind(); } updateCull(shadow_cam, result); @@ -8213,17 +8304,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera stop_glerror(); gGLLastMatrix = NULL; - { - //LLGLDepthTest depth(GL_TRUE); - //glClear(GL_DEPTH_BUFFER_BIT); - } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); stop_glerror(); - //glCullFace(GL_FRONT); - LLVertexBuffer::unbind(); { @@ -8231,10 +8315,14 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera { //occlusion program is general purpose depth-only no-textures gOcclusionProgram.bind(); } + else + { + gDeferredShadowProgram.bind(); + } gGL.diffuseColor4f(1,1,1,1); gGL.setColorMask(false, false); - + LLFastTimer ftm(FTM_SHADOW_SIMPLE); gGL.getTexUnit(0)->disable(); for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) @@ -8263,6 +8351,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLFastTimer ftm(FTM_SHADOW_ALPHA); gDeferredShadowAlphaMaskProgram.bind(); gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f); + gDeferredShadowAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | @@ -8279,7 +8368,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera //glCullFace(GL_BACK); - gDeferredShadowProgram.bind(); + gDeferredShadowCubeProgram.bind(); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); doOcclusion(shadow_cam); @@ -9049,11 +9138,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadow[j].getViewport(gGLViewport); mShadow[j].clear(); + U32 target_width = mShadow[j].getWidth(); + { static LLCullResult result[4]; //LLGLEnable enable(GL_DEPTH_CLAMP_NV); - renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE); + renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, TRUE, target_width); } mShadow[j].flush(); @@ -9192,11 +9283,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadow[i+4].getViewport(gGLViewport); mShadow[i+4].clear(); + U32 target_width = mShadow[i+4].getWidth(); + static LLCullResult result[2]; LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4; - renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE); + renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE, target_width); mShadow[i+4].flush(); } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index ac13a200a..4ad8a5e19 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -118,8 +118,10 @@ public: void doResetVertexBuffers(); void resizeScreenTexture(); void releaseGLBuffers(); + void releaseLUTBuffers(); void releaseScreenBuffers(); void createGLBuffers(); + void createLUTBuffers(); void allocateScreenBuffer(U32 resX, U32 resY); bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples); @@ -165,6 +167,7 @@ public: void markRebuild(LLSpatialGroup* group, BOOL priority = FALSE); void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE); void markPartitionMove(LLDrawable* drawablep); + void markMeshDirty(LLSpatialGroup* group); //get the object between start and end that's closest to start. LLViewerObject* lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end, @@ -263,7 +266,7 @@ public: void generateSunShadow(LLCamera& camera); - void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, BOOL use_shader = TRUE, BOOL use_occlusion = TRUE); + void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, BOOL use_shader, BOOL use_occlusion, U32 target_width); void renderHighlights(); void renderDebug(); void renderPhysicsDisplay(); @@ -369,7 +372,7 @@ private: void removeFromQuickLookup( LLDrawPool* poolp ); BOOL updateDrawableGeom(LLDrawable* drawable, BOOL priority); void assertInitializedDoError(); - bool assertInitialized() { const bool is_init = isInit(); if (!is_init) assertInitializedDoError(); return is_init; } + bool assertInitialized() { const bool is_init = isInit(); if (!is_init) assertInitializedDoError(); return is_init; }; public: enum {GPU_CLASS_MAX = 3 }; @@ -410,7 +413,9 @@ public: RENDER_TYPE_VOLUME, RENDER_TYPE_PARTICLES, RENDER_TYPE_WL_CLOUDS, +#if ENABLE_CLASSIC_CLOUDS RENDER_TYPE_CLASSIC_CLOUDS, +#endif RENDER_TYPE_HUD_PARTICLES, NUM_RENDER_TYPES, END_RENDER_TYPES = NUM_RENDER_TYPES @@ -536,6 +541,9 @@ public: //utility buffer for rendering post effects, gets abused by renderDeferredLighting LLPointer mDeferredVB; + //utility buffer for rendering cubes, 8 vertices are corners of a cube [-1, 1] + LLPointer mCubeVB; + //sun shadow map LLRenderTarget mShadow[6]; std::vector mShadowFrustPoints[4]; @@ -587,6 +595,7 @@ public: BOOL mVertexShadersEnabled; S32 mVertexShadersLoaded; // 0 = no, 1 = yes, -1 = failed + U32 mTransformFeedbackPrimitives; //number of primitives expected to be generated by transform feedback protected: BOOL mRenderTypeEnabled[NUM_RENDER_TYPES]; std::stack mRenderTypeEnableStack; @@ -644,6 +653,9 @@ protected: LLSpatialGroup::sg_vector_t mGroupQ1; //priority LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority + LLSpatialGroup::sg_vector_t mMeshDirtyGroup; //groups that need rebuildMesh called + U32 mMeshDirtyQueryObject; + LLDrawable::drawable_list_t mPartitionQ; //drawables that need to update their spatial partition radius bool mGroupQ2Locked; diff --git a/indra/newview/rlvcommon.cpp b/indra/newview/rlvcommon.cpp index 78f5e05e3..4a4e1ff81 100644 --- a/indra/newview/rlvcommon.cpp +++ b/indra/newview/rlvcommon.cpp @@ -16,20 +16,25 @@ #include "llviewerprecompiledheaders.h" #include "llagent.h" -#include "llappviewer.h" +#include "llagentui.h" #include "llavatarnamecache.h" #include "llnotificationsutil.h" #include "lluictrlfactory.h" #include "sgversion.h" #include "llviewermenu.h" #include "llviewerparcelmgr.h" +#include "llviewermenu.h" #include "llviewerregion.h" #include "llviewerstats.h" #include "llvoavatar.h" #include "llworld.h" #include "rlvcommon.h" +#include "rlvhelper.h" #include "rlvhandler.h" +#include "rlvlocks.h" + +#include using namespace LLOldEvents; @@ -39,7 +44,7 @@ using namespace LLOldEvents; #ifdef RLV_EXTENSION_NOTIFY_BEHAVIOUR // Checked: 2009-12-05 (RLVa-1.1.0h) | Added: RLVa-1.1.0h -void RlvNotifications::notifyBehaviour(ERlvBehaviour eBhvr, ERlvParamType eType) +/*void RlvNotifications::notifyBehaviour(ERlvBehaviour eBhvr, ERlvParamType eType) { const std::string& strMsg = RlvStrings::getBehaviourNotificationString(eBhvr, eType); if (!strMsg.empty()) @@ -48,19 +53,11 @@ void RlvNotifications::notifyBehaviour(ERlvBehaviour eBhvr, ERlvParamType eType) argsNotify["MESSAGE"] = strMsg; LLNotificationsUtil::add("SystemMessageTip", argsNotify); } -} +}*/ #endif // RLV_EXTENSION_NOTIFY_BEHAVIOUR -// Checked: 2010-10-11 (RLVa-1.1.3c) | Added: RLVa-1.1.3c -void RlvNotifications::notifyBlocked(const std::string& strRlvString) -{ - LLSD argsNotify; - argsNotify["MESSAGE"] = RlvStrings::getString(strRlvString); - LLNotificationsUtil::add("SystemMessageTip", argsNotify); -} - -// Checked: 2009-11-11 (RLVa-1.1.0a) | Added: RLVa-1.1.0a -void RlvNotifications::notifyBlockedViewXXX(const char* pstrAssetType) +// Checked: 2009-11-11 (RLVa-1.1.0a) | Added: RLVa-1.1.0a/ +/*void RlvNotifications::notifyBlockedViewXXX(const char* pstrAssetType) { LLStringUtil::format_map_t argsMsg; std::string strMsg = RlvStrings::getString(RLV_STRING_BLOCKED_VIEWXXX); argsMsg["[TYPE]"] = pstrAssetType; @@ -70,16 +67,16 @@ void RlvNotifications::notifyBlockedViewXXX(const char* pstrAssetType) argsNotify["MESSAGE"] = strMsg; LLNotificationsUtil::add("SystemMessageTip", argsNotify); } - +*/ // Checked: 2009-11-13 (RLVa-1.1.0b) | Modified: RLVa-1.1.0b -void RlvNotifications::warnGiveToRLV() +void RlvUtil::warnGiveToRLV() { if ( (gSavedSettings.getWarning(RLV_SETTING_FIRSTUSE_GIVETORLV)) && (RlvSettings::getForbidGiveToRLV()) ) - LLNotifications::instance().add(RLV_SETTING_FIRSTUSE_GIVETORLV, LLSD(), LLSD(), &RlvNotifications::onGiveToRLVConfirmation); + LLNotifications::instance().add(RLV_SETTING_FIRSTUSE_GIVETORLV, LLSD(), LLSD(), &RlvUtil::onGiveToRLVConfirmation); } // Checked: 2009-11-13 (RLVa-1.1.0b) | Modified: RLVa-1.1.0b -void RlvNotifications::onGiveToRLVConfirmation(const LLSD& notification, const LLSD& response) +void RlvUtil::onGiveToRLVConfirmation(const LLSD& notification, const LLSD& response) { gSavedSettings.setWarning(RLV_SETTING_FIRSTUSE_GIVETORLV, FALSE); @@ -93,11 +90,12 @@ void RlvNotifications::onGiveToRLVConfirmation(const LLSD& notification, const L // #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS -BOOL RlvSettings::fCompositeFolders = FALSE; +bool RlvSettings::fCompositeFolders = false; #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS -BOOL RlvSettings::fLegacyNaming = TRUE; -BOOL RlvSettings::fNoSetEnv = FALSE; -BOOL RlvSettings::fShowNameTags = FALSE; +bool RlvSettings::fCanOOC = true; +bool RlvSettings::fLegacyNaming = true; +bool RlvSettings::fNoSetEnv = false; +bool RlvSettings::fShowNameTags = false; // Checked: 2009-12-18 (RLVa-1.1.0k) | Modified: RLVa-1.1.0i void RlvSettings::initClass() @@ -106,21 +104,31 @@ void RlvSettings::initClass() if (!fInitialized) { #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS - fCompositeFolders = rlvGetSettingBOOL(RLV_SETTING_ENABLECOMPOSITES, FALSE); + fCompositeFolders = rlvGetSetting(RLV_SETTING_ENABLECOMPOSITES, false); if (gSavedSettings.controlExists(RLV_SETTING_ENABLECOMPOSITES)) gSavedSettings.getControl(RLV_SETTING_ENABLECOMPOSITES)->getSignal()->connect(boost::bind(&onChangedSettingBOOL, _2, &fCompositeFolders)); #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS - fLegacyNaming = rlvGetSettingBOOL(RLV_SETTING_ENABLELEGACYNAMING, TRUE); + fLegacyNaming = rlvGetSetting(RLV_SETTING_ENABLELEGACYNAMING, true); if (gSavedSettings.controlExists(RLV_SETTING_ENABLELEGACYNAMING)) gSavedSettings.getControl(RLV_SETTING_ENABLELEGACYNAMING)->getSignal()->connect(boost::bind(&onChangedSettingBOOL, _2, &fLegacyNaming)); - fNoSetEnv = rlvGetSettingBOOL(RLV_SETTING_NOSETENV, FALSE); + fCanOOC = rlvGetSetting(RLV_SETTING_CANOOC, true); + fNoSetEnv = rlvGetSetting(RLV_SETTING_NOSETENV, false); - fShowNameTags = rlvGetSettingBOOL(RLV_SETTING_SHOWNAMETAGS, FALSE); + fShowNameTags = rlvGetSetting(RLV_SETTING_SHOWNAMETAGS, false); if (gSavedSettings.controlExists(RLV_SETTING_SHOWNAMETAGS)) gSavedSettings.getControl(RLV_SETTING_SHOWNAMETAGS)->getSignal()->connect(boost::bind(&onChangedSettingBOOL, _2, &fShowNameTags)); +#ifdef RLV_EXTENSION_STARTLOCATION + // Don't allow toggling RLVaLoginLastLocation from the debug settings floater + if (gSavedPerAccountSettings.controlExists(RLV_SETTING_LOGINLASTLOCATION)) + gSavedPerAccountSettings.getControl(RLV_SETTING_LOGINLASTLOCATION)->setHiddenFromSettingsEditor(true); +#endif // RLV_EXTENSION_STARTLOCATION + + if (gSavedSettings.controlExists(RLV_SETTING_AVATAROFFSET_Z)) + gSavedSettings.getControl(RLV_SETTING_AVATAROFFSET_Z)->getSignal()->connect(boost::bind(&onChangedAvatarOffset, _2)); + fInitialized = true; } } @@ -129,7 +137,7 @@ void RlvSettings::initClass() // Checked: 2010-04-01 (RLVa-1.2.0c) | Modified: RLVa-0.2.1d void RlvSettings::updateLoginLastLocation() { - if (gSavedPerAccountSettings.controlExists(RLV_SETTING_LOGINLASTLOCATION)) + if ( (!LLApp::isQuitting()) && (gSavedPerAccountSettings.controlExists(RLV_SETTING_LOGINLASTLOCATION)) ) { BOOL fValue = (gRlvHandler.hasBehaviour(RLV_BHVR_TPLOC)) || (!gRlvHandler.canStand()); if (gSavedPerAccountSettings.getBOOL(RLV_SETTING_LOGINLASTLOCATION) != fValue) @@ -141,11 +149,16 @@ void RlvSettings::initClass() } #endif // RLV_EXTENSION_STARTLOCATION -// Checked: 2009-12-18 (RLVa-1.1.0k) | Added: RLVa-1.1.0i -bool RlvSettings::onChangedSettingBOOL(const LLSD& newvalue, BOOL* pfSetting) +// Checked: 2010-10-11 (RLVa-1.2.0e) | Added: RLVa-1.2.0e +bool RlvSettings::onChangedAvatarOffset(const LLSD& sdValue) +{ + gAgent.sendAgentSetAppearance(); + return true; +} +bool RlvSettings::onChangedSettingBOOL(const LLSD& sdValue, bool* pfSetting) { if (pfSetting) - *pfSetting = newvalue.asBoolean(); + *pfSetting = sdValue.asBoolean(); return true; } @@ -156,8 +169,8 @@ bool RlvSettings::onChangedSettingBOOL(const LLSD& newvalue, BOOL* pfSetting) std::vector RlvStrings::m_Anonyms; std::map RlvStrings::m_StringMap; #ifdef RLV_EXTENSION_NOTIFY_BEHAVIOUR -std::map RlvStrings::m_BhvrAddMap; -std::map RlvStrings::m_BhvrRemMap; +/*std::map RlvStrings::m_BhvrAddMap; +std::map RlvStrings::m_BhvrRemMap;*/ #endif // RLV_EXTENSION_NOTIFY_BEHAVIOUR // Checked: 2010-03-09 (RLVa-1.2.0a) | Added: RLVa-1.1.0h @@ -195,7 +208,7 @@ void RlvStrings::initClass() } } #ifdef RLV_EXTENSION_NOTIFY_BEHAVIOUR - else if (pNode->hasName("behaviour-notifications")) + /*else if (pNode->hasName("behaviour-notifications")) { std::string strBhvr, strType; ERlvBehaviour eBhvr; for (LLXMLNode* pNotifyNode = pNode->getFirstChild(); pNotifyNode != NULL; pNotifyNode = pNotifyNode->getNextSibling()) @@ -211,7 +224,7 @@ void RlvStrings::initClass() else if ("rem" == strType) m_BhvrRemMap.insert(std::pair(eBhvr, pNotifyNode->getTextContents())); } - } + }*/ #endif // RLV_EXTENSION_NOTIFY_BEHAVIOUR } @@ -239,7 +252,7 @@ const std::string& RlvStrings::getAnonym(const std::string& strName) #ifdef RLV_EXTENSION_NOTIFY_BEHAVIOUR // Checked: 2009-12-05 (RLVa-1.1.0h) | Added: RLVa-1.1.0h -const std::string& RlvStrings::getBehaviourNotificationString(ERlvBehaviour eBhvr, ERlvParamType eType) +/*const std::string& RlvStrings::getBehaviourNotificationString(ERlvBehaviour eBhvr, ERlvParamType eType) { if (RLV_TYPE_ADD == eType) { @@ -252,7 +265,7 @@ const std::string& RlvStrings::getBehaviourNotificationString(ERlvBehaviour eBhv return (itString != m_BhvrRemMap.end()) ? itString->second : LLStringUtil::null; } return LLStringUtil::null; -} +}*/ #endif // RLV_EXTENSION_NOTIFY_BEHAVIOUR // Checked: 2009-11-11 (RLVa-1.1.0a) | Added: RLVa-1.1.0a @@ -346,20 +359,19 @@ void RlvUtil::filterLocation(std::string& strUTF8Text) LLWorld::region_list_t regions = LLWorld::getInstance()->getRegionList(); const std::string& strHiddenRegion = RlvStrings::getString(RLV_STRING_HIDDEN_REGION); for (LLWorld::region_list_t::const_iterator itRegion = regions.begin(); itRegion != regions.end(); ++itRegion) - rlvStringReplace(strUTF8Text, (*itRegion)->getName(), strHiddenRegion); + boost::ireplace_all(strUTF8Text, (*itRegion)->getName(), strHiddenRegion); // Filter any mention of the parcel name LLViewerParcelMgr* pParcelMgr = LLViewerParcelMgr::getInstance(); if (pParcelMgr) - rlvStringReplace(strUTF8Text, pParcelMgr->getAgentParcelName(), RlvStrings::getString(RLV_STRING_HIDDEN_PARCEL)); + boost::ireplace_all(strUTF8Text, pParcelMgr->getAgentParcelName(), RlvStrings::getString(RLV_STRING_HIDDEN_PARCEL)); } // Checked: 2010-12-08 (RLVa-1.2.2c) | Modified: RLVa-1.2.2c void RlvUtil::filterNames(std::string& strUTF8Text, bool fFilterLegacy) { - std::vector idAgents; + uuid_vec_t idAgents; LLWorld::getInstance()->getAvatars(&idAgents, NULL); - for (int idxAgent = 0, cntAgent = idAgents.size(); idxAgent < cntAgent; idxAgent++) { LLAvatarName avName; @@ -369,21 +381,24 @@ void RlvUtil::filterNames(std::string& strUTF8Text, bool fFilterLegacy) // NOTE: if the legacy first and last name are empty we get a legacy name of " " which would replace all spaces in the string std::string strLegacyName; - if ( (fFilterLegacy) && (!avName.mIsDisplayNameDefault) && (!avName.mLegacyFirstName.empty()) ) + if ( (fFilterLegacy) && (!avName.mLegacyFirstName.empty()) && + ((!avName.mIsDisplayNameDefault) || (LLCacheName::getDefaultLastName() == avName.mLegacyLastName)) ) + { strLegacyName = avName.getLegacyName(); + } // If the display name is a subset of the legacy name we need to filter that first, otherwise it's the other way around - if (std::string::npos != strLegacyName.find(avName.mDisplayName)) + if (boost::icontains(strLegacyName, avName.mDisplayName)) { if (!strLegacyName.empty()) - rlvStringReplace(strUTF8Text, strLegacyName, strAnonym); - rlvStringReplace(strUTF8Text, avName.mDisplayName, strAnonym); + boost::ireplace_all(strUTF8Text, strLegacyName, strAnonym); + boost::ireplace_all(strUTF8Text, avName.mDisplayName, strAnonym); } else { - rlvStringReplace(strUTF8Text, avName.mDisplayName, strAnonym); + boost::ireplace_all(strUTF8Text, avName.mDisplayName, strAnonym); if (!strLegacyName.empty()) - rlvStringReplace(strUTF8Text, strLegacyName, strAnonym); + boost::ireplace_all(strUTF8Text, strLegacyName, strAnonym); } } } @@ -424,15 +439,28 @@ bool RlvUtil::isNearbyRegion(const std::string& strRegion) return false; } +// Checked: 2011-04-11 (RLVa-1.3.0h) | Modified: RLVa-1.3.0h +void RlvUtil::notifyBlocked(const std::string& strNotifcation, const LLSD& sdArgs) +{ + std::string strMsg = RlvStrings::getString(strNotifcation); + LLStringUtil::format(strMsg, sdArgs); + + LLSD sdNotify; + sdNotify["MESSAGE"] = strMsg; + LLNotificationsUtil::add("SystemMessageTip", sdNotify); +} + // Checked: 2010-11-11 (RLVa-1.2.1g) | Added: RLVa-1.2.1g void RlvUtil::notifyFailedAssertion(const std::string& strAssert, const std::string& strFile, int nLine) { + // Don't show the same assertion over and over, or if the user opted out static std::string strAssertPrev, strFilePrev; static int nLinePrev; - if ( (strAssertPrev == strAssert) && (strFile == strFilePrev) && (nLine == nLinePrev) ) + if ( ((strAssertPrev == strAssert) && (strFile == strFilePrev) && (nLine == nLinePrev)) || + (!rlvGetSetting(RLV_SETTING_SHOWASSERTIONFAIL, true)) ) { - // Don't show the same assertion over and over return; } + strAssertPrev = strAssert; strFilePrev = strFile; nLinePrev = nLine; @@ -447,7 +475,7 @@ void RlvUtil::sendBusyMessage(const LLUUID& idTo, const std::string& strMsg, con { // [See process_improved_im()] std::string strFullName; - gAgent.buildFullname(strFullName); + LLAgentUI::buildFullname(strFullName); pack_instant_message(gMessageSystem, gAgent.getID(), FALSE, gAgent.getSessionID(), idTo, strFullName, strMsg, IM_ONLINE, IM_BUSY_AUTO_RESPONSE, idSession); @@ -479,6 +507,25 @@ bool RlvUtil::sendChatReply(S32 nChannel, const std::string& strUTF8Text) // Generic menu enablers // +// Checked: 2010-04-23 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g +BOOL rlvMenuCheckEnabled(void*) +{ + return rlv_handler_t::isEnabled(); +} + +// Checked: 2010-04-23 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g +void rlvMenuToggleEnabled(void*) +{ + gSavedSettings.setBOOL(RLV_SETTING_MAIN, !rlv_handler_t::isEnabled()); + + LLSD args; + args["MESSAGE"] = + llformat("RestrainedLove Support will be %s after you restart", (rlv_handler_t::isEnabled()) ? "disabled" : "enabled" ); + LLNotificationsUtil::add("GenericAlert", args); + + return; +} + bool RlvEnableIfNot::handleEvent(LLPointer, const LLSD& userdata) { bool fEnable = true; @@ -495,6 +542,21 @@ bool RlvEnableIfNot::handleEvent(LLPointer, const LLSD& userdata) // Selection functors // +// Checked: 2010-04-11 (RLVa-1.2.0b) | Modified: RLVa-0.2.0g +bool rlvCanDeleteOrReturn() +{ + if ( (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) || (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) ) + { + struct RlvCanDeleteOrReturn : public LLSelectedObjectFunctor + { + /*virtual*/ bool apply(LLViewerObject* pObj) { return pObj->isReturnable(); } + } f; + LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); + return (hSel.notNull()) && (0 != hSel->getRootObjectCount()) && (hSel->applyToRootObjects(&f, false)); + } + return true; +} + // Checked: 2010-04-20 (RLVa-1.2.0f) | Modified: RLVa-0.2.0f bool RlvSelectHasLockedAttach::apply(LLSelectNode* pNode) { @@ -508,16 +570,10 @@ bool RlvSelectIsEditable::apply(LLSelectNode* pNode) return (pObj) && (!gRlvHandler.canEdit(pObj)); } -// Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-0.2.0f -bool RlvSelectIsOwnedByOrGroupOwned::apply(LLSelectNode* pNode) -{ - return (pNode->mPermissions->isGroupOwned()) || (pNode->mPermissions->getOwner() == m_idAgent); -} - -// Checked: 2010-04-01 (RLVa-1.2.0c) | Modified: RLVa-0.2.0f +// Checked: 2011-05-28 (RLVa-1.4.0a) | Modified: RLVa-1.4.0a bool RlvSelectIsSittingOn::apply(LLSelectNode* pNode) { - return (pNode->getObject()) && (pNode->getObject()->getRootEdit() == m_pObject); + return (pNode->getObject()) && (pNode->getObject()->getRootEdit()->isChild(m_pAvatar)); } // ============================================================================ @@ -582,19 +638,36 @@ bool rlvPredCanNotRemoveItem(const LLViewerInventoryItem* pItem) return !rlvPredCanRemoveItem(pItem); } +// Checked: 2010-04-24 (RLVa-1.2.0f) | Added: RLVa-1.2.0f +RlvPredIsEqualOrLinkedItem::RlvPredIsEqualOrLinkedItem(const LLUUID& idItem) +{ + m_pItem = gInventory.getItem(idItem); +} + +// Checked: 2010-04-24 (RLVa-1.2.0f) | Added: RLVa-1.2.0f +bool RlvPredIsEqualOrLinkedItem::operator()(const LLViewerInventoryItem* pItem) const +{ + return (m_pItem) && (pItem) && (m_pItem->getLinkedUUID() == pItem->getLinkedUUID()); +} + // ============================================================================ // Various public helper functions // -// Checked: 2010-09-28 (RLVa-1.1.3b) | Modified: RLVa-1.1.3b -BOOL rlvAttachToEnabler(void* pParam) +// Checked: 2009-11-15 (RLVa-1.1.0c) | Added: RLVa-1.1.0c +/* +BOOL rlvEnableSharedWearEnabler(void* pParam) { - // Visually disable an option on the "Attach to (HUD)" submenu if: - // - the attachment point is locked non-detachable with an object attached - // - the attachment point is locked non-attachable - return (pParam != NULL) && - (!gRlvAttachmentLocks.hasLockedAttachment((LLViewerJointAttachment*)pParam)) && - (!gRlvAttachmentLocks.isLockedAttachmentPoint((LLViewerJointAttachment*)pParam, RLV_LOCK_ADD)); + return false; + // Visually disable the "Enable Shared Wear" option when at least one attachment is non-detachable + return (!gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE)); +} +*/ + +// Checked: 2010-11-01 (RLVa-1.2.2a) | Added: RLVa-1.2.2a +const std::string& rlvGetAnonym(const LLAvatarName& avName) +{ + return RlvStrings::getAnonym(avName); } // ============================================================================ diff --git a/indra/newview/rlvcommon.h b/indra/newview/rlvcommon.h index ac097ab5d..e44c06f57 100644 --- a/indra/newview/rlvcommon.h +++ b/indra/newview/rlvcommon.h @@ -17,99 +17,107 @@ #ifndef RLV_COMMON_H #define RLV_COMMON_H -#include "llmemberlistener.h" -#include "llinventorymodel.h" +#include "llavatarname.h" #include "llselectmgr.h" -#include "llview.h" #include "llviewercontrol.h" -#include "llviewerinventory.h" +#include "llmemberlistener.h" + #include "rlvdefines.h" -#include "rlvviewer2.h" + +#ifdef LL_WINDOWS + #pragma warning (push) + #pragma warning (disable : 4702) // warning C4702: unreachable code +#endif +#include +#ifdef LL_WINDOWS + #pragma warning (pop) +#endif + +using namespace LLOldEvents; // ============================================================================ // Forward declarations // -class RlvCommand; - -typedef std::vector c_llvo_vec_t; - -// ============================================================================ -// RlvNotifications // +// General viewer source +// +class LLInventoryItem; +class LLViewerInventoryCategory; +class LLViewerInventoryItem; +class LLViewerJointAttachment; +class LLWearable; -class RlvNotifications -{ -public: - static void notifyBehaviour(ERlvBehaviour eBhvr, ERlvParamType eType); - static void notifyBlockedTeleport() { notifyBlocked("blocked_teleport"); } - static void notifyBlockedViewNote() { notifyBlockedViewXXX(LLAssetType::lookup(LLAssetType::AT_NOTECARD)); } - static void notifyBlockedViewScript() { notifyBlockedViewXXX(LLAssetType::lookup(LLAssetType::AT_SCRIPT)); } - static void notifyBlockedViewTexture() { notifyBlockedViewXXX(LLAssetType::lookup(LLAssetType::AT_TEXTURE)); } +// +// RLVa-specific +// +class RlvCommand; +typedef std::list rlv_command_list_t; +class RlvObject; - static void warnGiveToRLV(); -protected: - static void notifyBlocked(const std::string& strRlvString); - static void notifyBlockedViewXXX(const char* pstrAssetType); +struct RlvException; +typedef boost::variant RlvExceptionOption; - static void onGiveToRLVConfirmation(const LLSD& notification, const LLSD& response); -}; +class RlvGCTimer; // ============================================================================ // RlvSettings // -inline BOOL rlvGetSettingBOOL(const std::string& strSetting, BOOL fDefault) +template inline T rlvGetSetting(const std::string& strSetting, const T& defaultValue) { - return (gSavedSettings.controlExists(strSetting)) ? gSavedSettings.getBOOL(strSetting) : fDefault; + RLV_ASSERT_DBG(gSavedSettings.controlExists(strSetting)); + return (gSavedSettings.controlExists(strSetting)) ? gSavedSettings.get(strSetting) : defaultValue; } -inline BOOL rlvGetPerUserSettingsBOOL(const std::string& strSetting, BOOL fDefault) + +template inline T rlvGetPerUserSetting(const std::string& strSetting, const T& defaultValue) { - return (gSavedPerAccountSettings.controlExists(strSetting)) ? gSavedPerAccountSettings.getBOOL(strSetting) : fDefault; -} -inline std::string rlvGetSettingString(const std::string& strSetting, const std::string& strDefault) -{ - return (gSavedSettings.controlExists(strSetting)) ? gSavedSettings.getString(strSetting) : strDefault; + RLV_ASSERT_DBG(gSavedPerAccountSettings.controlExists(strSetting)); + return (gSavedPerAccountSettings.controlExists(strSetting)) ? gSavedPerAccountSettings.get(strSetting) : defaultValue; } class RlvSettings { public: - static BOOL getDebug() { return rlvGetSettingBOOL(RLV_SETTING_DEBUG, FALSE); } - static BOOL getForbidGiveToRLV() { return rlvGetSettingBOOL(RLV_SETTING_FORBIDGIVETORLV, TRUE); } - static BOOL getNoSetEnv() { return fNoSetEnv; } + static F32 getAvatarOffsetZ() { return rlvGetSetting(RLV_SETTING_AVATAROFFSET_Z, 0.0); } + static bool getDebug() { return rlvGetSetting(RLV_SETTING_DEBUG, false); } + static bool getCanOOC() { return fCanOOC; } + static bool getForbidGiveToRLV() { return rlvGetSetting(RLV_SETTING_FORBIDGIVETORLV, true); } + static bool getNoSetEnv() { return fNoSetEnv; } - static std::string getWearAddPrefix() { return rlvGetSettingString(RLV_SETTING_WEARADDPREFIX, LLStringUtil::null); } - static std::string getWearReplacePrefix() { return rlvGetSettingString(RLV_SETTING_WEARREPLACEPREFIX, LLStringUtil::null); } + static std::string getWearAddPrefix() { return rlvGetSetting(RLV_SETTING_WEARADDPREFIX, LLStringUtil::null); } + static std::string getWearReplacePrefix() { return rlvGetSetting(RLV_SETTING_WEARREPLACEPREFIX, LLStringUtil::null); } - static bool getDebugHideUnsetDup() { return rlvGetSettingBOOL(RLV_SETTING_DEBUGHIDEUNSETDUP, FALSE); } + static bool getDebugHideUnsetDup() { return rlvGetSetting(RLV_SETTING_DEBUGHIDEUNSETDUP, false); } #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS static BOOL getEnableComposites() { return fCompositeFolders; } #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS - static BOOL getEnableLegacyNaming() { return fLegacyNaming; } - static BOOL getEnableWear() { return TRUE; } - static BOOL getEnableSharedWear() { return rlvGetSettingBOOL(RLV_SETTING_ENABLESHAREDWEAR, FALSE); } - static BOOL getHideLockedLayers() { return rlvGetSettingBOOL(RLV_SETTING_HIDELOCKEDLAYER, FALSE); } - static BOOL getHideLockedAttach() { return rlvGetSettingBOOL(RLV_SETTING_HIDELOCKEDATTACH, FALSE); } - static BOOL getHideLockedInventory() { return rlvGetSettingBOOL(RLV_SETTING_HIDELOCKEDINVENTORY, FALSE); } - static BOOL getSharedInvAutoRename() { return rlvGetSettingBOOL(RLV_SETTING_SHAREDINVAUTORENAME, TRUE); } - static BOOL getShowNameTags() { return fShowNameTags; } + static bool getEnableLegacyNaming() { return fLegacyNaming; } + static bool getEnableSharedWear() { return rlvGetSetting(RLV_SETTING_ENABLESHAREDWEAR, false); } + static bool getHideLockedLayers() { return rlvGetSetting(RLV_SETTING_HIDELOCKEDLAYER, false); } + static bool getHideLockedAttach() { return rlvGetSetting(RLV_SETTING_HIDELOCKEDATTACH, false); } + static bool getHideLockedInventory() { return rlvGetSetting(RLV_SETTING_HIDELOCKEDINVENTORY, false); } + static bool getSharedInvAutoRename() { return rlvGetSetting(RLV_SETTING_SHAREDINVAUTORENAME, true); } + static bool getShowNameTags() { return fShowNameTags; } #ifdef RLV_EXTENSION_STARTLOCATION - static BOOL getLoginLastLocation() { return rlvGetPerUserSettingsBOOL(RLV_SETTING_LOGINLASTLOCATION, TRUE); } + static bool getLoginLastLocation() { return rlvGetPerUserSetting(RLV_SETTING_LOGINLASTLOCATION, true); } static void updateLoginLastLocation(); #endif // RLV_EXTENSION_STARTLOCATION static void initClass(); protected: - static bool onChangedSettingBOOL(const LLSD& newvalue, BOOL* pfSetting); + static bool onChangedAvatarOffset(const LLSD& sdValue); + static bool onChangedMenuLevel(); + static bool onChangedSettingBOOL(const LLSD& sdValue, bool* pfSetting); #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS static BOOL fCompositeFolders; #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS - static BOOL fLegacyNaming; - static BOOL fNoSetEnv; - static BOOL fShowNameTags; + static bool fCanOOC; + static bool fLegacyNaming; + static bool fNoSetEnv; + static bool fShowNameTags; }; // ============================================================================ @@ -121,6 +129,7 @@ class RlvStrings public: static void initClass(); + static const std::string& getAnonym(const LLAvatarName& avName); // @shownames static const std::string& getAnonym(const std::string& strName); // @shownames static const std::string& getBehaviourNotificationString(ERlvBehaviour eBhvr, ERlvParamType eType); static const std::string& getString(const std::string& strStringName); @@ -133,10 +142,6 @@ public: protected: static std::vector m_Anonyms; static std::map m_StringMap; - #ifdef RLV_EXTENSION_NOTIFY_BEHAVIOUR - static std::map m_BhvrAddMap; - static std::map m_BhvrRemMap; - #endif // RLV_EXTENSION_NOTIFY_BEHAVIOUR }; // ============================================================================ @@ -156,6 +161,9 @@ public: static bool isForceTp() { return m_fForceTp; } static void forceTp(const LLVector3d& posDest); // Ignores restrictions that might otherwise prevent tp'ing + static void notifyBlocked(const std::string& strNotifcation, const LLSD& sdArgs = LLSD()); + static void notifyBlockedGeneric() { notifyBlocked(RLV_STRING_BLOCKED_GENERIC); } + static void notifyBlockedViewXXX(LLAssetType::EType assetType) { notifyBlocked(RLV_STRING_BLOCKED_VIEWXXX, LLSD().with("[TYPE]", LLAssetType::lookup(assetType))); } static void notifyFailedAssertion(const std::string& strAssert, const std::string& strFile, int nLine); static void sendBusyMessage(const LLUUID& idTo, const std::string& strMsg, const LLUUID& idSession = LLUUID::null); @@ -163,6 +171,8 @@ public: static bool sendChatReply(S32 nChannel, const std::string& strUTF8Text); static bool sendChatReply(const std::string& strChannel, const std::string& strUTF8Text); + static void warnGiveToRLV(); + static void onGiveToRLVConfirmation(const LLSD& notification, const LLSD& response); protected: static bool m_fForceTp; // @standtp }; @@ -171,13 +181,6 @@ protected: // Extensibility classes // -class RlvBehaviourObserver -{ -public: - virtual ~RlvBehaviourObserver() {} - virtual void changed(const RlvCommand& rlvCmd, bool fInternal) = 0; -}; - class RlvCommandHandler { public: @@ -193,15 +196,21 @@ typedef bool (RlvCommandHandler::*rlvCommandHandler)(const RlvCommand& rlvCmd, E // Generic menu enablers // +BOOL rlvMenuCheckEnabled(void*); +void rlvMenuToggleEnabled(void*); +//void rlvMenuToggleVisible(void*); +//bool rlvMenuEnableIfNot(const LLSD& sdParam); class RlvEnableIfNot : public LLMemberListener { - bool handleEvent(LLPointer, const LLSD&); + bool handleEvent(LLPointer, const LLSD&); }; // ============================================================================ // Selection functors // +bool rlvCanDeleteOrReturn(); + struct RlvSelectHasLockedAttach : public LLSelectedNodeFunctor { RlvSelectHasLockedAttach() {} @@ -215,28 +224,14 @@ struct RlvSelectIsEditable : public LLSelectedNodeFunctor /*virtual*/ bool apply(LLSelectNode* pNode); }; -struct RlvSelectIsOwnedByOrGroupOwned : public LLSelectedNodeFunctor -{ - RlvSelectIsOwnedByOrGroupOwned(const LLUUID& uuid) : m_idAgent(uuid) {} - virtual bool apply(LLSelectNode* pNode); -protected: - LLUUID m_idAgent; -}; - struct RlvSelectIsSittingOn : public LLSelectedNodeFunctor { - RlvSelectIsSittingOn(LLXform* pObject) : m_pObject(pObject) {} - virtual bool apply(LLSelectNode* pNode); + RlvSelectIsSittingOn(const LLVOAvatar* pAvatar) : m_pAvatar(pAvatar) {} + /*virtual*/ bool apply(LLSelectNode* pNode); protected: - LLXform* m_pObject; + const LLVOAvatar* m_pAvatar; }; -// ============================================================================ -// Various public helper functions -// - -BOOL rlvAttachToEnabler(void* pParam); - // ============================================================================ // Predicates // @@ -265,12 +260,8 @@ protected: struct RlvPredIsEqualOrLinkedItem { RlvPredIsEqualOrLinkedItem(const LLViewerInventoryItem* pItem) : m_pItem(pItem) {} - RlvPredIsEqualOrLinkedItem(const LLUUID& idItem) { m_pItem = gInventory.getItem(idItem); } - - bool operator()(const LLViewerInventoryItem* pItem) const - { - return (m_pItem) && (pItem) && (m_pItem->getLinkedUUID() == pItem->getLinkedUUID()); - } + RlvPredIsEqualOrLinkedItem(const LLUUID& idItem); + bool operator()(const LLViewerInventoryItem* pItem) const; protected: const LLViewerInventoryItem* m_pItem; }; @@ -285,6 +276,12 @@ template struct RlvPredValuesEqual // Inlined class member functions // +// Checked: 2010-10-31 (RLVa-1.2.2a) | Added: RLVa-1.2.2a +inline const std::string& RlvStrings::getAnonym(const LLAvatarName& avName) +{ + return getAnonym(avName.mDisplayName); +} + // Checked: 2010-03-26 (RLVa-1.2.0b) | Modified: RLVa-1.0.2a inline bool RlvUtil::isEmote(const std::string& strUTF8Text) { diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index 74b28359e..17118d4fa 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -58,7 +58,7 @@ #ifdef RLV_EXPERIMENTAL_CMDS #define RLV_EXTENSION_CMD_ALLOWIDLE // Forces "Away" status when idle (effect is the same as setting AllowIdleAFK to TRUE) #define RLV_EXTENSION_CMD_GETCOMMAND // @getcommand: