[mapguide-commits] r6048 - in trunk/MgDev: Common/MapGuideCommon/Services Common/MapGuideCommon/Util Common/PlatformBase/MapLayer Oem/ACE/ACE_wrappers/ace Server/src/Common Server/src/Common/Manager Server/src/Core Web/src/mapviewerjava Web/src/mapviewernet Web/src/mapviewerphp

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Tue Aug 9 02:21:33 EDT 2011


Author: liuar
Date: 2011-08-08 23:21:33 -0700 (Mon, 08 Aug 2011)
New Revision: 6048

Modified:
   trunk/MgDev/Common/MapGuideCommon/Services/SiteInfo.cpp
   trunk/MgDev/Common/MapGuideCommon/Services/SiteInfo.h
   trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.cpp
   trunk/MgDev/Common/MapGuideCommon/Util/IpUtil.cpp
   trunk/MgDev/Common/MapGuideCommon/Util/IpUtil.h
   trunk/MgDev/Common/PlatformBase/MapLayer/MapBase.h
   trunk/MgDev/Oem/ACE/ACE_wrappers/ace/config-linux.h
   trunk/MgDev/Oem/ACE/ACE_wrappers/ace/config-win32.h
   trunk/MgDev/Server/src/Common/Manager/SessionCache.cpp
   trunk/MgDev/Server/src/Common/stdafx.h
   trunk/MgDev/Server/src/Core/Server.cpp
   trunk/MgDev/Web/src/mapviewerjava/common.jsp
   trunk/MgDev/Web/src/mapviewerjava/quickplotgeneratepicture.jsp
   trunk/MgDev/Web/src/mapviewernet/common.aspx
   trunk/MgDev/Web/src/mapviewernet/quickplotgeneratepicture.aspx
   trunk/MgDev/Web/src/mapviewerphp/common.php
   trunk/MgDev/Web/src/mapviewerphp/quickplotgeneratepicture.php
Log:
Submit on behalf of Mars Wu
Implements RFC 118 - IPv6 Support
Ticket: http://trac.osgeo.org/mapguide/ticket/1767

Modified: trunk/MgDev/Common/MapGuideCommon/Services/SiteInfo.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/SiteInfo.cpp	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Common/MapGuideCommon/Services/SiteInfo.cpp	2011-08-09 06:21:33 UTC (rev 6048)
@@ -15,6 +15,7 @@
 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 #include "MapGuideCommon.h"
+#include "Base64.h"
 
 MG_IMPL_DYNCREATE(MgSiteInfo);
 
@@ -60,22 +61,30 @@
     m_adminPort(0),
     m_target(L""),
     m_status(Uninitialized)
-{
-    if(hexString.length() >= HexStringLength)
     {
-        UINT32 n1, n2, n3, n4;
+        // Compose a format string to extract the target address and the ports from the hexstring
+        INT32 targetlen = (INT32) hexString.length() - HexPortsStringLength;
+        wchar_t format[20] = {0};
+        swprintf(format, 20, L"%%%ds%%4X%%4X%%4X", targetlen);
 
-        // Read the IP parts into their variables
-        if(::swscanf(hexString.c_str(), L"%2X%2X%2X%2X%4X%4X%4X", &n1, &n2, &n3, &n4, &m_sitePort, &m_clientPort, &m_adminPort) == 7)
+        wchar_t targetHex[100] = {0};
+        if (::swscanf(hexString.c_str(), format, targetHex, &m_sitePort, &m_clientPort, &m_adminPort) == 4)
         {
-            // Write the 4 'n' values into an IP string
-            wchar_t buffer[20];
-            swprintf(buffer, 20, L"%u.%u.%u.%u", n1, n2, n3, n4);
-            m_target = buffer;
+            char buffer[100] = {0};
+            INT32 hexLength = targetlen;
+            STRING targetHexOriginal = targetHex;
+            // There were alignment "=" removed. They should be appended back to do decoding
+            if (0 != targetlen % 4)
+            {
+                targetHexOriginal.append(L"===");
+                hexLength = 4 * (targetlen / 4 + 1);
+            }
+
+            Base64::Decode((unsigned char*)buffer, ACE_Wide_To_Ascii(targetHexOriginal.c_str()).char_rep(), hexLength);
+            m_target = ACE_Ascii_To_Wide(buffer).wchar_rep();
             m_status = Ok;
         }
     }
-}
 
 ///----------------------------------------------------------------------------
 /// <summary>
@@ -141,15 +150,20 @@
 /// </summary>
 STRING MgSiteInfo::ToHexString()
 {
-    STRING hexString;
-    UINT32 n1, n2, n3, n4;
-    wchar_t buffer[30];
-    if (4 == ::swscanf(m_target.c_str(), L"%u.%u.%u.%u", &n1, &n2, &n3, &n4))
+    char buf[100] = {0};
+    Base64::Encode(buf, (unsigned char*)ACE_Wide_To_Ascii(m_target.c_str()).char_rep(), (unsigned long) m_target.length());
+    
+    // Remove the alignment "="
+    STRING targetHex = ACE_Ascii_To_Wide(buf).wchar_rep();
+    if (targetHex.find(L"=") != targetHex.npos)
     {
-        swprintf(buffer, 30, L"%.2X%.2X%.2X%.2X%.4X%.4X%.4X", n1, n2, n3, n4, m_sitePort, m_clientPort, m_adminPort);
-        hexString = buffer;
+        targetHex = targetHex.substr(0, targetHex.find(L"="));
     }
-    return hexString;
+    
+    wchar_t buffer[100] = {0};	
+    swprintf(buffer, 100, L"%s%.4X%.4X%.4X", targetHex.c_str(), m_sitePort, m_clientPort, m_adminPort);
+
+    return STRING(buffer);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -208,3 +222,4 @@
 }
 
 
+

Modified: trunk/MgDev/Common/MapGuideCommon/Services/SiteInfo.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/SiteInfo.h	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Common/MapGuideCommon/Services/SiteInfo.h	2011-08-09 06:21:33 UTC (rev 6048)
@@ -15,6 +15,7 @@
 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 #include "MapGuideCommon.h"
+#include "Base64.h"
 
 #ifndef MG_SITEINFO_H_
 #define MG_SITEINFO_H_
@@ -81,7 +82,8 @@
     // Retrieve a hex string that encodes the site info connection params
     STRING ToHexString();
 
-    static const INT32 HexStringLength = 20;
+    // The length of the hexstring where the port numbers of admin, client and site are encoded
+    static const INT32 HexPortsStringLength = 12;
 
 protected:
 

Modified: trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.cpp	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.cpp	2011-08-09 06:21:33 UTC (rev 6048)
@@ -322,23 +322,19 @@
     {
         size_t length = sessionId.length();
 
-        if (length > MgSiteInfo::HexStringLength)
+        STRING siteHexString = sessionId.substr(sessionId.rfind(L"_") + 1);
+        Ptr<MgSiteInfo> siteInfo = GetSiteInfo(siteHexString);
+
+        if ((NULL != siteInfo.p) && (MgSiteInfo::Ok == siteInfo->GetStatus()))
         {
-            STRING siteHexString = sessionId.substr(
-                length - MgSiteInfo::HexStringLength, MgSiteInfo::HexStringLength);
-            Ptr<MgSiteInfo> siteInfo = GetSiteInfo(siteHexString);
+            connProps = GetConnectionProperties(userInfo, siteInfo, portType);
+        }
+        else
+        {
+            // This site is not currently working
 
-            if ((NULL != siteInfo.p) && (MgSiteInfo::Ok == siteInfo->GetStatus()))
-            {
-                connProps = GetConnectionProperties(userInfo, siteInfo, portType);
-            }
-            else
-            {
-                // This site is not currently working
-
-                // We have a session, but it will not exist on any other machine so we force the session exception
-                throw new MgSessionExpiredException(L"MgSiteManager.GetConnectionProperties",__LINE__,__WFILE__, NULL, L"", NULL);
-            }
+            // We have a session, but it will not exist on any other machine so we force the session exception
+            throw new MgSessionExpiredException(L"MgSiteManager.GetConnectionProperties",__LINE__,__WFILE__, NULL, L"", NULL);
         }
     }
     else
@@ -503,35 +499,44 @@
 {
     Ptr<MgSiteInfo> matchingSiteInfo;
 
-    if(hexString.length() >= MgSiteInfo::HexStringLength)
+    INT32 sitePort, clientPort, adminPort;
+    STRING target;
+
+    // Compose a format string to extract the target address and the ports from the hexstring
+    INT32 targetlen = (INT32) hexString.length() - MgSiteInfo::HexPortsStringLength;
+    wchar_t format[20] = {0};
+    swprintf(format, 20, L"%%%ds%%4X%%4X%%4X", targetlen);
+
+    wchar_t targetHex[100] = {0};
+    if (::swscanf(hexString.c_str(), format, targetHex, &sitePort, &clientPort, &adminPort) == 4)
     {
-        UINT32 n1, n2, n3, n4;
-        INT32 sitePort, clientPort, adminPort;
-        STRING target;
-
-        // Read the IP parts into their variables
-        if(::swscanf(hexString.c_str(), L"%2X%2X%2X%2X%4X%4X%4X", &n1, &n2, &n3, &n4, &sitePort, &clientPort, &adminPort) == 7)
+        char buffer[100] = {0};
+        INT32 hexLength = targetlen;
+        STRING targetHexOriginal = targetHex;
+        // There were alignment "=" removed during encoding. They should be appended back to do decoding
+        if (0 != targetlen % 4)
         {
-            // Write the 4 'n' values into an IP string
-            wchar_t buffer[20];
-            swprintf(buffer, 20, L"%u.%u.%u.%u", n1, n2, n3, n4);
-            target = buffer;
+            targetHexOriginal.append(L"===");
+            hexLength = 4 * (targetlen / 4 + 1);
         }
 
-        ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, NULL));
+        Base64::Decode((unsigned char*)buffer, ACE_Wide_To_Ascii(targetHexOriginal.c_str()).char_rep(), hexLength);
+        target = ACE_Ascii_To_Wide(buffer).wchar_rep();
+    }
 
-        for (INT32 i = 0; i < (INT32)m_sites.size(); i++)
+    ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, NULL));
+
+    for (INT32 i = 0; i < (INT32)m_sites.size(); i++)
+    {
+        MgSiteInfo* siteInfo = m_sites.at(i);
+
+        if (siteInfo->GetTarget() == target
+            && (siteInfo->GetPort(MgSiteInfo::Site)   == sitePort ||
+            siteInfo->GetPort(MgSiteInfo::Client) == clientPort ||
+            siteInfo->GetPort(MgSiteInfo::Admin)  == adminPort))
         {
-            MgSiteInfo* siteInfo = m_sites.at(i);
-
-            if (siteInfo->GetTarget() == target
-                && (siteInfo->GetPort(MgSiteInfo::Site)   == sitePort ||
-                    siteInfo->GetPort(MgSiteInfo::Client) == clientPort ||
-                    siteInfo->GetPort(MgSiteInfo::Admin)  == adminPort))
-            {
-                matchingSiteInfo = SAFE_ADDREF(siteInfo);
-                break;
-            }
+            matchingSiteInfo = SAFE_ADDREF(siteInfo);
+            break;
         }
     }
 

Modified: trunk/MgDev/Common/MapGuideCommon/Util/IpUtil.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Util/IpUtil.cpp	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Common/MapGuideCommon/Util/IpUtil.cpp	2011-08-09 06:21:33 UTC (rev 6048)
@@ -42,7 +42,7 @@
 
 ///----------------------------------------------------------------------------
 /// <summary>
-/// Detemines whether or not the specified host is an IP address.
+/// Determines whether or not the specified host is an IP address.
 /// </summary>
 ///
 /// <param name="address">
@@ -55,21 +55,204 @@
 ///
 /// EXCEPTIONS:
 /// MgNullArgumentException
-/// MgInvalidArgumentException
 /// MgInvalidIpAddressException
 ///----------------------------------------------------------------------------
 
 bool MgIpUtil::IsIpAddress(CREFSTRING address, bool strict)
 {
-    ValidateAddress(address, strict);
+    return IsIpv4Address(address, strict) || IsIpv6Address(address, strict);
+}
 
+///----------------------------------------------------------------------------
+/// <summary>
+/// Determines whether or not the specified host is an IP address in IPv4 format.
+/// </summary>
+///
+/// <param name="address">
+/// IP address (or host name).
+/// </param>
+/// </param>
+/// <param name="strict">
+/// Flag indicating if the specified address must be looked up.
+/// </param>
+///
+/// EXCEPTIONS:
+/// MgNullArgumentException
+/// MgInvalidIpAddressException
+///----------------------------------------------------------------------------
+
+bool MgIpUtil::IsIpv4Address(CREFSTRING address, bool strict)
+{
+    if (address.empty())
+    {
+        throw new MgNullArgumentException(L"MgIpUtil.IsIpv4Address",
+            __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
     unsigned int n1, n2, n3, n4;
+    bool isv4Address = 4 == ::swscanf(address.c_str(), L"%u.%u.%u.%u", &n1, &n2, &n3, &n4);
 
-    return (4 == ::swscanf(address.c_str(), L"%u.%u.%u.%u", &n1, &n2, &n3, &n4));
+    if (isv4Address && strict)
+    {
+        ACE_INET_Addr inetAddr;
+
+        if (0 != inetAddr.set((u_short)0, address.c_str()) ||
+            NULL == inetAddr.get_host_name())
+        {
+            MgStringCollection arguments;
+            arguments.Add(address);
+
+            throw new MgInvalidIpAddressException(L"MgIpUtil.IsIpv4Address",
+                __LINE__, __WFILE__, &arguments, L"", NULL);
+        }
+
+        isv4Address = AF_INET == inetAddr.get_type();
+    }
+
+    return isv4Address;
 }
 
 ///----------------------------------------------------------------------------
 /// <summary>
+/// Determines whether or not the specified host is an IP address in IPv6 format.
+/// </summary>
+///
+/// <param name="address">
+/// IP address (or host name).
+/// </param>
+/// </param>
+/// <param name="strict">
+/// Flag indicating if the specified address must be looked up.
+/// </param>
+///
+/// EXCEPTIONS:
+/// MgNullArgumentException
+/// MgInvalidIpAddressException
+///----------------------------------------------------------------------------
+
+bool MgIpUtil::IsIpv6Address(CREFSTRING address, bool strict)
+{
+    if (address.empty())
+    {
+        throw new MgNullArgumentException(L"MgIpUtil.IsIpv6Address",
+            __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    // An valid IPv6 address must have ":"
+    bool isv6Address = address.find(L":") != -1;
+
+    if (isv6Address)
+    {
+        // Check if the address is expressed
+        int expressed = (int) address.find(L"::");
+        if (address.rfind(L"::") != expressed)
+        {
+            // There are more than 1 "::", it's an invalid address
+            return false;
+        }
+        expressed = expressed == -1 ? 0 : 1;
+
+        int conlonNumber = 0;
+        const wchar_t *addr = address.c_str();
+        int len = (int) wcslen(addr);
+
+        if (addr[len] == L':')
+        {
+            // If the last char is :, it's an invalid address
+            return false;
+        }
+
+        if (addr[0] == L':' && addr[1] != L':')
+        {
+            // Single ":" cannot be the leading character for an valid IPv6 address
+            return false;
+        }
+
+        // Check how many ":" the address has
+        for (int i = 0; i < len; ++i)
+        {
+            if (addr[i] == L':')
+            {
+                ++conlonNumber;
+            }
+        }
+        
+        if (conlonNumber > 7 || conlonNumber < 1)
+        {
+            // If there are more than 8 groups or less than 1 group, it's an invalid address
+            return false;
+        }
+
+        int totalGroups = 8;
+        // Get how many groups are expressed as ::
+        // It's possible that "::" is the leading character, then 1 more group is expressed
+        int compressedGroups = totalGroups - conlonNumber + (addr[0] == L':' ? 1 : 0);
+
+        wchar_t fullAddress[40] = {0};
+        wcscpy(fullAddress, L"0000:0000:0000:0000:0000:0000:0000:0000");
+
+        int digits = 0;
+        int index = (int) wcslen(fullAddress) - 1;
+        wchar_t lastChar = L' ';
+        for (int i = len - 1; i >= 0 && index >= 0; --i, --index)
+        {
+            if (addr[i] == L':')
+            {
+                if (lastChar == L':')
+                {
+                    // Restore the compressed groups
+                    index -= compressedGroups * 5 - 1;
+                }
+                else
+                {
+                    // Restore the addtional leading 0s
+                    index -= 4 - digits;
+                }
+
+                // A new group will start, then reset the digits counter
+                digits = 0;
+            }
+            else
+            {
+                fullAddress[index] = addr[i];
+
+                // The max number of digits in a group is 4
+                if (++digits > 4)
+                {
+                    return false;
+                }
+            }
+
+            lastChar = addr[i];
+        }
+
+        // Check if the digits in each group are valid hex numbers
+        int n1, n2, n3, n4, n5, n6, n7, n8;
+        isv6Address = 8 == ::swscanf(fullAddress, L"%4X:%4X:%4X:%4X:%4X:%4X:%4X:%4X:", &n1, &n2, &n3, &n4, &n5, &n6, &n7, &n8);
+
+        if (isv6Address & strict)
+        {
+            ACE_INET_Addr inetAddr;
+
+            if (0 != inetAddr.set((u_short)0, address.c_str()) ||
+                NULL == inetAddr.get_host_name())
+            {
+                MgStringCollection arguments;
+                arguments.Add(address);
+
+                throw new MgInvalidIpAddressException(L"MgIpUtil.IsIpv6Address",
+                    __LINE__, __WFILE__, &arguments, L"", NULL);
+            }
+
+            isv6Address = AF_INET6 == inetAddr.get_type();
+        }
+    }
+
+    return isv6Address;
+}
+
+///----------------------------------------------------------------------------
+/// <summary>
 /// Detemines whether or not the specified host is local.
 /// </summary>
 ///
@@ -90,7 +273,8 @@
     bool isLocalHost = false;
 
     if (0 == ::wcscmp(address.c_str(), L"127.0.0.1")
-     || 0 == _wcsnicmp(address.c_str(), L"localhost", ::wcslen(L"localhost")))
+        || 0 == ::wcscmp(address.c_str(), L"::1")
+        || 0 == _wcsnicmp(address.c_str(), L"localhost", ::wcslen(L"localhost")))
     {
         isLocalHost = true;
     }
@@ -217,7 +401,6 @@
 ///
 /// EXCEPTIONS:
 /// MgNullArgumentException
-/// MgInvalidArgumentException
 /// MgInvalidIpAddressException
 ///----------------------------------------------------------------------------
 
@@ -229,20 +412,6 @@
             __LINE__, __WFILE__, NULL, L"", NULL);
     }
 
-    if (STRING::npos != address.rfind(L':'))
-    {
-        MgStringCollection arguments;
-        arguments.Add(L"1");
-        arguments.Add(address);
-
-        MgStringCollection whyArguments;
-        whyArguments.Add(L":");
-
-        throw new MgInvalidArgumentException(L"MgIpUtil.ValidateAddress",
-            __LINE__, __WFILE__, &arguments,
-            L"MgStringContainsReservedCharacters", &whyArguments);
-    }
-
     if (strict)
     {
         ACE_INET_Addr inetAddr;
@@ -469,12 +638,6 @@
         ValidateAddress(address1, !IsLocalHost(address1, false));
         ValidateAddress(address2, !IsLocalHost(address2, false));
     }
-    else if (IsIpAddress(address1, false) && IsIpAddress(address2, false) &&
-            !IsLocalHost(address1, false) && !IsLocalHost(address2, false))
-    {
-        ValidateAddress(address1);
-        ValidateAddress(address2);
-    }
     else
     {
         ACE_INET_Addr inetAddr1((u_short)0, address1.c_str());
@@ -509,6 +672,32 @@
             {
                 compareFlag = 0;
             }
+            // If one of the addresses is IPv6 and the other one is IPv4, then even the two addresses 
+            // are for a same host, inetAddr1 == inetAddr2 is still false.
+            // And the case of both addresses are IPv6 and for a same host are already handled before
+            else if (inetAddr1.get_type() == AF_INET6 || inetAddr2.get_type() == AF_INET6)
+            {
+                // Convert them to addresses first then convert them to names.
+                // This is a workaround for the special case where the domain and the
+                // DNS suffix are different, e.g.:
+                //      name1 = calpc220.amer.ads.autodesk.com
+                //      name2 = calpc220.ads.autodesk.com
+                STRING addr1, addr2;
+                if (HostNameToAddress(address1, addr1) &&
+                    HostNameToAddress(address2, addr2))
+                {
+                    STRING name1, name2;
+
+                    if (HostAddressToName(addr1, name1) &&
+                        HostAddressToName(addr2, name2))
+                    {
+                        compareFlag = _wcsnicmp(name1.c_str(), name2.c_str(),
+                                                ACE_MIN(name1.length(), name2.length()));
+                    }
+                    // else, MgInvalidIpAddressException will be thrown
+                }
+                // else, MgInvalidIpAddressException will be thrown
+            }
             else if (inetAddr1 < inetAddr2)
             {
                 compareFlag = -1;

Modified: trunk/MgDev/Common/MapGuideCommon/Util/IpUtil.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Util/IpUtil.h	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Common/MapGuideCommon/Util/IpUtil.h	2011-08-09 06:21:33 UTC (rev 6048)
@@ -51,7 +51,6 @@
     /// Flag indicating if the specified address must be looked up.
     ///
     /// \exception MgNullArgumentException
-    /// \exception MgInvalidArgumentException
     /// \exception MgInvalidIpAddressException
     ///
     ///
@@ -60,6 +59,36 @@
 
     ///////////////////////////////////////////////////////////////////////////
     /// \brief
+    /// Determines whether or not the specified host is an IP address in IPv4 format.
+    ///
+    /// \param address
+    /// IP address (or host name).
+    /// \param strict
+    /// Flag indicating if the specified address must be looked up.
+    /// \exception MgNullArgumentException
+    /// \exception MgInvalidIpAddressException
+    ///
+    ///
+
+    static bool IsIpv4Address(CREFSTRING address, bool strict = true);
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Determines whether or not the specified host is an IP address in IPv6 format.
+    ///
+    /// \param address
+    /// IP address (or host name).
+    /// \param strict
+    /// Flag indicating if the specified address must be looked up.
+    /// \exception MgNullArgumentException
+    /// \exception MgInvalidIpAddressException
+    ///
+    ///
+
+    static bool IsIpv6Address(CREFSTRING address, bool strict = true);
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// \brief
     /// Determines whether or not the specified host is local.
     ///
     /// \param address

Modified: trunk/MgDev/Common/PlatformBase/MapLayer/MapBase.h
===================================================================
--- trunk/MgDev/Common/PlatformBase/MapLayer/MapBase.h	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Common/PlatformBase/MapLayer/MapBase.h	2011-08-09 06:21:33 UTC (rev 6048)
@@ -440,10 +440,30 @@
     /// \return
     /// Returns the number of dots per inch of the map display.
     ///
-    virtual INT32 GetDisplayDpi();  /// __get
+    virtual INT32 GetDisplayDpi();  /// __get, __set
 
     //////////////////////////////////////////////////////////////////
     /// \brief
+    /// Sets the number of dots per inch of the map display.
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// void SetDisplayDpi(int dpi);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// void SetDisplayDpi(int dpi);
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// void SetDisplayDpi(int dpi);
+    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \param dpi (int)
+    /// Number of dots per inch of the map display
+    ///
+    virtual void SetDisplayDpi(INT32 dpi);
+
+    //////////////////////////////////////////////////////////////////
+    /// \brief
     /// Returns the current width of the map display in pixels.
     ///
     /// \remarks
@@ -540,17 +560,28 @@
     ///
     virtual double GetFiniteDisplayScaleAt(INT32 index);
 
-EXTERNAL_API:
-
     //////////////////////////////////////////////////////////////////
     /// \brief
     /// Returns the background color for the map
     ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// string GetBackgroundColor();
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// string GetBackgroundColor();
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// string GetBackgroundColor();
+    /// \htmlinclude SyntaxBottom.html
+    ///
     /// \return
     /// Background color.
     ///
     virtual STRING GetBackgroundColor();
 
+EXTERNAL_API:
+
 INTERNAL_API:
 
     static MdfModel::MapDefinition* GetMapDefinition(MgResourceService* svcResource, MgResourceIdentifier* resId);
@@ -636,15 +667,6 @@
     virtual void SetDataExtent(MgEnvelope* extent);
 
     /// \brief
-    /// Sets the number of dots per inch of the map display
-    /// This method is for use by the viewers and should not be called directly
-    ///
-    /// \param dpi
-    /// Number of dots per inch of the map display
-    ///
-    virtual void SetDisplayDpi(INT32 dpi);
-
-    /// \brief
     /// Sets the current width of the map display in pixels
     /// This method is for use by the viewers and should not be called directly
     ///

Modified: trunk/MgDev/Oem/ACE/ACE_wrappers/ace/config-linux.h
===================================================================
--- trunk/MgDev/Oem/ACE/ACE_wrappers/ace/config-linux.h	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Oem/ACE/ACE_wrappers/ace/config-linux.h	2011-08-09 06:21:33 UTC (rev 6048)
@@ -8,6 +8,7 @@
 #ifndef ACE_CONFIG_LINUX_H
 #define ACE_CONFIG_LINUX_H
 #include /**/ "ace/pre.h"
+#define ACE_HAS_IPV6
 
 #define ACE_PLATFORM_CONFIG config-linux.h
 

Modified: trunk/MgDev/Oem/ACE/ACE_wrappers/ace/config-win32.h
===================================================================
--- trunk/MgDev/Oem/ACE/ACE_wrappers/ace/config-win32.h	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Oem/ACE/ACE_wrappers/ace/config-win32.h	2011-08-09 06:21:33 UTC (rev 6048)
@@ -18,6 +18,7 @@
 #ifndef ACE_CONFIG_WIN32_H
 #define ACE_CONFIG_WIN32_H
 #include /**/ "ace/pre.h"
+#define ACE_HAS_IPV6
 
 // NOTE: Please do not add anything besides #include's here.  Put other stuff
 //       (definitions, etc.) in the included headers

Modified: trunk/MgDev/Server/src/Common/Manager/SessionCache.cpp
===================================================================
--- trunk/MgDev/Server/src/Common/Manager/SessionCache.cpp	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Server/src/Common/Manager/SessionCache.cpp	2011-08-09 06:21:33 UTC (rev 6048)
@@ -150,7 +150,7 @@
     // Session Affinity: Check that the session was created by this server
     if(!session.empty())
     {
-        STRING hexString = session.substr(session.length() - MgSiteInfo::HexStringLength);
+        STRING hexString = session.substr(session.rfind(L"_") + 1); 
         Ptr<MgSiteInfo> sessionSiteInfo = new MgSiteInfo(hexString);
         if(sessionSiteInfo->GetStatus() == MgSiteInfo::Ok)
         {

Modified: trunk/MgDev/Server/src/Common/stdafx.h
===================================================================
--- trunk/MgDev/Server/src/Common/stdafx.h	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Server/src/Common/stdafx.h	2011-08-09 06:21:33 UTC (rev 6048)
@@ -20,8 +20,6 @@
 #ifndef STDAFX_H
 #define STDAFX_H
 
-#define _WIN32_WINNT 0x0400
-
 #define WIN32_LEAN_AND_MEAN     // Exclude rarely-used stuff from Windows headers
 // Windows Header Files:
 #include <windows.h>

Modified: trunk/MgDev/Server/src/Core/Server.cpp
===================================================================
--- trunk/MgDev/Server/src/Core/Server.cpp	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Server/src/Core/Server.cpp	2011-08-09 06:21:33 UTC (rev 6048)
@@ -523,9 +523,12 @@
                 pServerManager->SetClientMessageQueue(clientThreads.msg_queue_);
                 pServerManager->SetSiteMessageQueue(siteThreads.msg_queue_);
 
-                ACE_INET_Addr clientAddr((u_short)pServerManager->GetClientPort());
-                ACE_INET_Addr adminAddr((u_short)pServerManager->GetAdminPort());
-                ACE_INET_Addr siteAddr((u_short)pServerManager->GetSitePort());
+                // For IPv4, always listen to 0.0.0.0 so that the server could be connected through any valid v4 addresess
+                // For IPv6, always listen to :: so that the server could be connected through any valid v6 addresess
+                STRING listenToAddress = MgIpUtil::IsIpv4Address(pServerManager->GetLocalServerAddress()) ? L"0.0.0.0" : L"::";
+                ACE_INET_Addr clientAddr((u_short)pServerManager->GetClientPort(), listenToAddress.c_str());
+                ACE_INET_Addr adminAddr((u_short)pServerManager->GetAdminPort(), listenToAddress.c_str());
+                ACE_INET_Addr siteAddr((u_short)pServerManager->GetSitePort(), listenToAddress.c_str());
 
                 MgClientAcceptor clientAcceptor(clientAddr, ACE_Reactor::instance(), clientThreads.msg_queue_);
                 nResult = clientAcceptor.Initialize();

Modified: trunk/MgDev/Web/src/mapviewerjava/common.jsp
===================================================================
--- trunk/MgDev/Web/src/mapviewerjava/common.jsp	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Web/src/mapviewerjava/common.jsp	2011-08-09 06:21:33 UTC (rev 6048)
@@ -203,10 +203,11 @@
 
 String ValidateSessionId(String proposedSessionId)
 {
-    // 00000000-0000-0000-0000-000000000000_aa_00000000000000000000
+    // 00000000-0000-0000-0000-000000000000_aa_[aaaaaaaaaaaaa]000000000000
+    // the [aaaaaaaaaaaaa] is a based64 string and in variant length
     String validSessionId = "";
     if(proposedSessionId != null &&
-        Pattern.matches("^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}_[A-Za-z]{2}_[A-Fa-f0-9]{20}$", proposedSessionId))
+        Pattern.matches("^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}_[A-Za-z]{2}_\\w+[A-Fa-f0-9]{12}$", proposedSessionId))
     {
         validSessionId = proposedSessionId;
     }

Modified: trunk/MgDev/Web/src/mapviewerjava/quickplotgeneratepicture.jsp
===================================================================
--- trunk/MgDev/Web/src/mapviewerjava/quickplotgeneratepicture.jsp	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Web/src/mapviewerjava/quickplotgeneratepicture.jsp	2011-08-09 06:21:33 UTC (rev 6048)
@@ -46,9 +46,18 @@
 %>
 
 <%
-    GetRequestParameters(request);
-    response.setContentType("image/png");
-    ImageIO.write(GenerateMap(printSize), "png", response.getOutputStream());
+    try
+    {
+        GetRequestParameters(request);
+        response.setContentType("image/png");
+        ImageIO.write(GenerateMap(printSize), "png", response.getOutputStream());
+    }
+    catch (MgException e)
+    {
+        response.setContentType("text/html");
+        out.write ("ERROR:" + e.GetExceptionMessage() + "<br />");
+        out.write (e.GetStackTrace() + "<br />");
+    }
 %>
 
 <%!
@@ -96,6 +105,8 @@
 
 BufferedImage GenerateMap(Size<Integer> size) throws MgException, IOException
 {
+    InitializeWebTier();
+    
     MgUserInformation userInfo = new MgUserInformation(sessionId);
     MgSiteConnection siteConnection = new MgSiteConnection();
     siteConnection.Open(userInfo);
@@ -116,23 +127,26 @@
     Size<Double> toSize = new Size<Double>(size1.width / size2.width * size.width, size1.height / size2.height * size.height);
     MgCoordinate center = captureBox.GetCentroid().GetCoordinate();
 
-    // Get the map agent url
-    // Get the correct http protocol
-    StringBuilder mapAgent = new StringBuilder(mapAgentPath);
-    String encodeMapName = URLEncoder.encode(mapName,"UTF-8");
-    mapAgent.append("?VERSION=1.0.0&OPERATION=GETMAPIMAGE")
-            .append("&SESSION=").append(sessionId)
-            .append("&MAPNAME=").append(encodeMapName)
-            .append("&FORMAT=PNG")
-            .append("&SETVIEWCENTERX=").append(center.GetX())
-            .append("&SETVIEWCENTERY=").append(center.GetY())
-            .append("&SETVIEWSCALE=").append(scaleDenominator)
-            .append("&SETDISPLAYDPI=").append(printDpi)
-            .append("&SETDISPLAYWIDTH=").append(String.valueOf(toSize.width))
-            .append("&SETDISPLAYHEIGHT=").append(String.valueOf(toSize.height))
-            .append("&CLIP=0");
-
-    BufferedImage image  = ImageIO.read(new URL(mapAgent.toString()));
+    map.SetDisplayDpi(printDpi);
+    String colorString = map.GetBackgroundColor();
+    // The returned color string is in AARRGGBB format. But the constructor of MgColor needs a string in RRGGBBAA format
+    colorString = colorString.substring(2, 8) + colorString.substring(0, 2);
+    MgColor color = new MgColor(colorString);
+    
+    MgByteReader mgReader = renderingService.RenderMap(map,
+                                                    selection,
+                                                    center,
+                                                    scaleDenominator,
+                                                    (int) Math.ceil(toSize.width),
+                                                    (int) Math.ceil(toSize.height),
+                                                    color,
+                                                    "PNG",
+                                                    false);
+    File tempImage = File.createTempFile(UUID.randomUUID().toString(), "png");
+    mgReader.ToFile(tempImage.getAbsolutePath());
+    BufferedImage image = ImageIO.read(tempImage);
+    tempImage.delete();
+    
     BufferedImage result = Math.abs(rotation) > Double.MIN_VALUE ? new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB) : image;
     Graphics2D graphics  = result.createGraphics();
 

Modified: trunk/MgDev/Web/src/mapviewernet/common.aspx
===================================================================
--- trunk/MgDev/Web/src/mapviewernet/common.aspx	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Web/src/mapviewernet/common.aspx	2011-08-09 06:21:33 UTC (rev 6048)
@@ -195,10 +195,11 @@
 
 String ValidateSessionId(String proposedSessionId)
 {
-    // 00000000-0000-0000-0000-000000000000_aa_00000000000000000000
+    // 00000000-0000-0000-0000-000000000000_aa_[aaaaaaaaaaaaa]000000000000
+    // the [aaaaaaaaaaaaa] is a based64 string and in variant length
     String validSessionId = "";
     if(proposedSessionId != null && System.Text.RegularExpressions.Regex.IsMatch(proposedSessionId,
-        "^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}_[A-Za-z]{2}_[A-Fa-f0-9]{20}$"))
+        "^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}_[A-Za-z]{2}_\\w+[A-Fa-f0-9]{12}$"))
     {
         validSessionId = proposedSessionId;
     }

Modified: trunk/MgDev/Web/src/mapviewernet/quickplotgeneratepicture.aspx
===================================================================
--- trunk/MgDev/Web/src/mapviewernet/quickplotgeneratepicture.aspx	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Web/src/mapviewernet/quickplotgeneratepicture.aspx	2011-08-09 06:21:33 UTC (rev 6048)
@@ -42,9 +42,18 @@
 
 <%
     Response.Charset = "utf-8";
-
-    GetRequestParameters();
-    GenerateMap(printSize);
+    
+    try
+    {
+        GetRequestParameters();
+        GenerateMap(printSize);
+    }
+    catch (MgException e)
+    {
+        Response.ContentType = "text/html";
+        Response.Write(string.Format("ERROR: {0} <br />", e.GetExceptionMessage()));
+        Response.Write(string.Format("{0} <br />", e.GetStackTrace()));
+    }
 %>
 
 <script runat="server">
@@ -95,6 +104,8 @@
 
 void GenerateMap(Size size)
 {
+    InitializeWebTier();
+    
     MgUserInformation userInfo = new MgUserInformation(sessionID);
     MgSiteConnection siteConnection = new MgSiteConnection();
     siteConnection.Open(userInfo);
@@ -115,65 +126,54 @@
     SizeF toSize = new SizeF(size1.Width / size2.Width * size.Width, size1.Height / size2.Height * size.Height);
     MgCoordinate center = captureBox.GetCentroid().GetCoordinate();
 
-    // Get the map agent url
-    // Get the correct http protocol
-    StringBuilder mapAgent = new StringBuilder(Request.IsSecureConnection ? "https://" : "http://");
-    // Get the correct port number
-    // Just use the 127.0.0.1 specificly to point to localhost. Because the WebExtension will
-    // be always on the same server with map agent.
-    mapAgent.Append("127.0.0.1").Append(":").Append(Request.ServerVariables["SERVER_PORT"]);
+    map.SetDisplayDpi(printDpi);
+    string colorString = map.GetBackgroundColor();
+    // The returned color string is in AARRGGBB format. But the constructor of MgColor needs a string in RRGGBBAA format
+    colorString = string.Format("{0}{1}", colorString.Substring(2, 6), colorString.Substring(0, 2));
+    MgColor color = new MgColor(colorString);
 
-    // Get the correct virtual directory
-    string url = Request.ServerVariables["URL"];
-    mapAgent.Append(url.Substring(0, url.IndexOf("/", 1)));
+    MgByteReader mgReader = renderingService.RenderMap(map,
+                                                        selection,
+                                                        center,
+                                                        scaleDenominator,
+                                                        (int) toSize.Width,
+                                                        (int) toSize.Height,
+                                                        color,
+                                                        "PNG",
+                                                        false);
 
-    mapAgent.Append("/mapagent/mapagent.fcgi?VERSION=1.0.0&OPERATION=GETMAPIMAGE")
-            .AppendFormat("&SESSION={0}", sessionID)
-            .AppendFormat("&MAPNAME={0}", HttpUtility.UrlEncode(mapName))
-            .Append("&FORMAT=PNG")
-            .AppendFormat("&SETVIEWCENTERX={0}", center.GetX())
-            .AppendFormat("&SETVIEWCENTERY={0}", center.GetY())
-            .AppendFormat("&SETVIEWSCALE={0}", scaleDenominator)
-            .AppendFormat("&SETDISPLAYDPI={0}", printDpi)
-            .AppendFormat("&SETDISPLAYWIDTH={0}", toSize.Width)
-            .AppendFormat("&SETDISPLAYHEIGHT={0}", toSize.Height)
-            .Append("&CLIP=0");
+    string tempImage = Path.GetTempFileName();
+    mgReader.ToFile(tempImage);
 
-    WebRequest request = WebRequest.Create(mapAgent.ToString());
-
-    using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
+    using (System.Drawing.Image image = Bitmap.FromFile(tempImage))
     {
-        if (response.StatusCode == HttpStatusCode.OK)
+        using (System.Drawing.Image result = Math.Abs(rotation) > double.Epsilon ? new Bitmap(size.Width, size.Height) : image)
         {
-            using (Bitmap image = new Bitmap(response.GetResponseStream()))
+            using (Graphics graphics = Graphics.FromImage(result))
             {
-                using (Bitmap result = Math.Abs(rotation) > double.Epsilon ? new Bitmap(size.Width, size.Height) : image)
+                if (Math.Abs(rotation) > double.Epsilon)
                 {
-                    using (Graphics graphics = Graphics.FromImage(result))
-                    {
-                        if (Math.Abs(rotation) > double.Epsilon)
-                        {
-                            graphics.TranslateTransform(size.Width / 2, size.Height / 2);
-                            graphics.RotateTransform((float)rotation);
-                            graphics.DrawImage(image, -image.Width / 2, -image.Height / 2);
-                        }
-                    }
+                    graphics.TranslateTransform(size.Width / 2, size.Height / 2);
+                    graphics.RotateTransform((float)rotation);
+                    graphics.DrawImage(image, -image.Width / 2, -image.Height / 2);
+                }
+            }
 
-                    DrawNorthArrow(result);
+            DrawNorthArrow(result);
 
-                    using (MemoryStream stream = new MemoryStream())
-                    {
-                        result.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
-                        Response.ContentType = "image/png";
-                        Response.BinaryWrite(stream.ToArray());
-                    }
-                }
+            using (MemoryStream stream = new MemoryStream())
+            {
+                result.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
+                Response.ContentType = "image/png";
+                Response.BinaryWrite(stream.ToArray());
             }
         }
     }
+        
+    File.Delete(tempImage);
 }
 
-void DrawNorthArrow(Bitmap image)
+void DrawNorthArrow(System.Drawing.Image image)
 {
     // The north arrow image is created under this dpi
     int naDpi = 300;

Modified: trunk/MgDev/Web/src/mapviewerphp/common.php
===================================================================
--- trunk/MgDev/Web/src/mapviewerphp/common.php	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Web/src/mapviewerphp/common.php	2011-08-09 06:21:33 UTC (rev 6048)
@@ -160,10 +160,11 @@
 
 function ValidateSessionId($proposedSessionId)
 {
-    // 00000000-0000-0000-0000-000000000000_aa_00000000000000000000
+    // 00000000-0000-0000-0000-000000000000_aa_[aaaaaaaaaaaaa]000000000000
+    // the [aaaaaaaaaaaaa] is a based64 string and in variant length
     $validSessionId = "";
     if($proposedSessionId != null &&
-        preg_match('/^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}_[A-Za-z]{2}_[A-Fa-f0-9]{20}$/', $proposedSessionId))
+        preg_match('/^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}_[A-Za-z]{2}_\\w+[A-Fa-f0-9]{12}$/', $proposedSessionId))
     {
         $validSessionId = $proposedSessionId;
     }

Modified: trunk/MgDev/Web/src/mapviewerphp/quickplotgeneratepicture.php
===================================================================
--- trunk/MgDev/Web/src/mapviewerphp/quickplotgeneratepicture.php	2011-08-08 15:55:46 UTC (rev 6047)
+++ trunk/MgDev/Web/src/mapviewerphp/quickplotgeneratepicture.php	2011-08-09 06:21:33 UTC (rev 6048)
@@ -13,8 +13,17 @@
     $printSize;
     $paperSize;
 
-    GetParameters();
-    GenerateMap($printSize);
+    try
+    {
+        GetParameters();
+        GenerateMap($printSize);
+    }
+    catch (MgException $e)
+    {
+        header ("Content-type: text/html");
+        echo "ERROR: " . $e->GetExceptionMessage() . "<br>";
+        echo $e->GetStackTrace() . "<br>";
+    }
 ?>
 
 <?php
@@ -70,6 +79,8 @@
     {
         global $sessionID, $mapName, $captureBox, $printSize, $normalizedCapture, $rotation, $scaleDenominator, $printDpi;
 
+        InitializeWebTier();
+        
         $userInfo         = new MgUserInformation($sessionID);
         $siteConnection   = new MgSiteConnection();
         $siteConnection->Open($userInfo);
@@ -89,32 +100,27 @@
         $toSize           = new Size($size1->width / $size2->width * $size->width, $size1->height / $size2->height * $size->height);
         $center           = $captureBox->GetCentroid()->GetCoordinate();
 
-        // Get the map agent url
-        // Get the correct http protocal
-        $mapAgent = "http";
-        if ($_SERVER["HTTPS"] == "on")
-        {
-            $mapAgent .= "s";
-        }
-        // Get the correct port number
-        // Just use the 127.0.0.1 specificly to point to localhost. Because the WebExtension will
-        // be always on the same server with map agent.
-        $mapAgent .= "://127.0.0.1:" . $_SERVER["SERVER_PORT"];
-        // Get the correct virtual directory
-        $mapAgent .= substr($_SERVER["REQUEST_URI"], 0, strpos($_SERVER["REQUEST_URI"], "/", 1));
-        $mapAgent .="/mapagent/mapagent.fcgi?VERSION=1.0.0&OPERATION=GETMAPIMAGE" .
-                    "&SESSION=$sessionID" .
-                    "&MAPNAME=" . rawurlencode($mapName) .
-                    "&FORMAT=PNG" .
-                    "&SETVIEWCENTERX=" . $center->GetX() .
-                    "&SETVIEWCENTERY=" . $center->GetY() .
-                    "&SETVIEWSCALE=$scaleDenominator" .
-                    "&SETDISPLAYDPI=$printDpi" .
-                    "&SETDISPLAYWIDTH=$toSize->width" .
-                    "&SETDISPLAYHEIGHT=$toSize->height" .
-                    "&CLIP=0";
+        $map->SetDisplayDpi($printDpi);
+        $colorString = $map->GetBackgroundColor();
+        // The returned color string is in AARRGGBB format. But the constructor of MgColor needs a string in RRGGBBAA format
+        $colorString = substr($colorString, 2, 6) . substr($colorString, 0, 2);
+        $color = new MgColor($colorString);
 
-        $image = imagecreatefrompng($mapAgent);
+        $mgReader = $renderingService->RenderMap($map, 
+                                                $selection, 
+                                                $center,
+                                                $scaleDenominator, 
+                                                $toSize->width, 
+                                                $toSize->height,
+                                                $color,
+                                                "PNG",
+                                                false);
+
+        $tempImage = sys_get_temp_dir() . uniqid();
+        $mgReader->ToFile($tempImage);
+        $image = imagecreatefrompng($tempImage);
+        unlink($tempImage);
+        
         // Rotate the picture back to be normalized
         $normalizedImg = imagerotate($image, -$rotation, 0);
         // Free the original image



More information about the mapguide-commits mailing list