Index: /trunk/src/VBox/Main/src-server/HostDnsService.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/HostDnsService.cpp	(revision 48330)
+++ /trunk/src/VBox/Main/src-server/HostDnsService.cpp	(revision 48330)
@@ -0,0 +1,105 @@
+/* $Id$
+/** @file
+ * Base class fo Host DNS & Co services.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <VBox/com/array.h>
+#include <VBox/com/ptr.h>
+#include <VBox/com/string.h>
+
+#include "HostDnsService.h"
+#include <iprt/thread.h>
+#include <iprt/semaphore.h>
+
+HostDnsService::HostDnsService(){}
+
+HostDnsService::~HostDnsService () 
+{
+    int rc = RTCritSectDelete(&m_hCritSect);
+    AssertRC(rc);
+}
+
+
+HRESULT HostDnsService::init (void) 
+{
+    int rc = RTCritSectInit(&m_hCritSect);
+    AssertRCReturn(rc, E_FAIL);
+    return S_OK;
+}
+
+HRESULT HostDnsService::start()
+{
+    return S_OK;
+}
+
+void HostDnsService::stop()
+{
+}
+
+HRESULT HostDnsService::update()
+{
+    return S_OK;
+}
+
+STDMETHODIMP HostDnsService::COMGETTER(NameServers)(ComSafeArrayOut(BSTR, aNameServers))
+{
+    RTCritSectEnter(&m_hCritSect);
+    com::SafeArray<BSTR> nameServers(m_llNameServers.size());
+
+    Utf8StrListIterator it;
+    int i = 0;
+    for (it = m_llNameServers.begin(); it != m_llNameServers.end(); ++it, ++i)
+        (*it).cloneTo(&nameServers[i]);
+
+    nameServers.detachTo(ComSafeArrayOutArg(aNameServers));
+
+    RTCritSectLeave(&m_hCritSect);
+
+    return S_OK;
+}
+
+
+STDMETHODIMP HostDnsService::COMGETTER(DomainName)(BSTR *aDomainName)
+{
+    RTCritSectEnter(&m_hCritSect);
+
+    m_DomainName.cloneTo(aDomainName);
+
+    RTCritSectLeave(&m_hCritSect);
+
+    return S_OK;
+}
+
+
+STDMETHODIMP HostDnsService::COMGETTER(SearchStrings)(ComSafeArrayOut(BSTR, aSearchStrings))
+{
+    RTCritSectEnter(&m_hCritSect);
+
+    com::SafeArray<BSTR> searchString(m_llSearchStrings.size());
+
+    Utf8StrListIterator it;
+    int i = 0;
+    for (it = m_llSearchStrings.begin(); it != m_llSearchStrings.end(); ++it, ++i)
+        (*it).cloneTo(&searchString[i]);
+
+
+    searchString.detachTo(ComSafeArrayOutArg(aSearchStrings));
+
+    RTCritSectLeave(&m_hCritSect);
+
+    return S_OK;
+}
+
+
Index: /trunk/src/VBox/Main/src-server/HostDnsService.h
===================================================================
--- /trunk/src/VBox/Main/src-server/HostDnsService.h	(revision 48330)
+++ /trunk/src/VBox/Main/src-server/HostDnsService.h	(revision 48330)
@@ -0,0 +1,138 @@
+/* $Id$ */
+/** @file
+ * Host DNS listener. 
+ */
+
+/*
+ * Copyright (C) 2005-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ___H_DNSHOSTSERVICE
+#define ___H_DNSHOSTSERVICE
+
+#include <iprt/cdefs.h>
+#include <iprt/critsect.h>
+#include <iprt/types.h>
+
+
+#include <list>
+
+typedef std::list<com::Utf8Str> Utf8StrList;
+typedef Utf8StrList::iterator Utf8StrListIterator;
+
+class HostDnsService
+{
+public: 
+    HostDnsService();
+    virtual ~HostDnsService();
+    virtual HRESULT init(void);
+    virtual HRESULT start(void);
+    virtual void stop(void);
+    STDMETHOD(COMGETTER(NameServers))(ComSafeArrayOut(BSTR, aNameServers));
+    STDMETHOD(COMGETTER(DomainName))(BSTR *aDomainName);
+    STDMETHOD(COMGETTER(SearchStrings))(ComSafeArrayOut(BSTR, aSearchStrings));
+protected:
+    virtual HRESULT update(void);
+
+    /* XXX: hide it with struct Data together with <list> */
+    Utf8StrList     m_llNameServers;
+    Utf8StrList     m_llSearchStrings;
+    com::Utf8Str        m_DomainName;
+    RTCRITSECT      m_hCritSect;
+
+private:
+    HostDnsService(const HostDnsService& service){ NOREF(service); }
+    HostDnsService& operator =(const HostDnsService& service){ NOREF(service); return *this; }
+};
+
+# ifdef RT_OS_DARWIN
+class HostDnsServiceDarwin: public HostDnsService
+{
+public:
+    HostDnsServiceDarwin();
+    virtual ~HostDnsServiceDarwin();
+
+    virtual HRESULT init(void);
+    virtual HRESULT start(void);
+    virtual void stop(void);
+    virtual HRESULT update();
+private:
+    static void hostDnsServiceStoreCallback(void *store, void *arrayRef, void *info);
+
+};
+# endif
+
+# ifdef RT_OS_WINDOWS
+class HostDnsServiceWin: public HostDnsService
+{
+public:
+    HostDnsServiceWin();
+    virtual ~HostDnsServiceWin();
+
+    virtual HRESULT init(void);
+    virtual HRESULT start(void);
+    virtual void stop(void);
+    virtual HRESULT update();
+private:
+    void strList2List(Utf8StrList& lst, char *strLst);
+};
+# endif
+
+#if defined(RT_OS_SOLARIS) || defined(RT_OS_LINUX) || defined(RT_OS_OS2)
+
+class HostDnsServiceResolvConf: public HostDnsService
+{
+public:
+    HostDnsServiceResolvConf(const char *aResolvConfFileName = "/etc/resolv.conf");
+    virtual ~HostDnsServiceResolvConf();
+    virtual HRESULT init(void);
+    virtual HRESULT update();
+protected:
+    com::Utf8Str m_ResolvConfFilename;
+    RTFILE m_ResolvConfFile;
+};
+
+#  if defined(RT_OS_SOLARIS)
+/**
+ * XXX: https://blogs.oracle.com/praks/entry/file_events_notification
+ */
+class HostDnsServiceSolaris: public HostDnsServiceResolvConf
+{
+public:
+    HostDnsServiceSolaris(){}
+    virtual ~HostDnsServiceSolaris(){}
+};
+#  elif defined(RT_OS_LINUX)
+/**
+ * XXX: http://www.ibm.com/developerworks/linux/library/l-ubuntu-inotify/index.html
+ */
+class HostDnsServiceLinux: public HostDnsServiceResolvConf
+{
+public:
+    HostDnsServiceLinux(){}
+    virtual ~HostDnsServiceLinux(){}
+};
+
+#  elif defined(RT_OS_OS2)
+class HostDnsServiceOs2: public HostDnsServiceResolvConf
+{
+public:
+    HostDnsServiceOs2()
+    {
+        /* XXX: \\MPTN\\ETC should be taken from environment variable ETC  */
+        ::HostDnsServiceResolvConf("\\MPTN\\ETC\\RESOLV2");
+    }
+    virtual ~HostDnsServiceOs2(){}
+};
+#  endif
+#endif
+
+#endif /* !___H_DNSHOSTSERVICE */
Index: /trunk/src/VBox/Main/src-server/HostDnsServiceResolvConf.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/HostDnsServiceResolvConf.cpp	(revision 48330)
+++ /trunk/src/VBox/Main/src-server/HostDnsServiceResolvConf.cpp	(revision 48330)
@@ -0,0 +1,133 @@
+/* -*- indent-tabs-mode: nil; -*- */
+#include <VBox/com/string.h>
+#include <VBox/com/ptr.h>
+
+#include "HostDnsService.h"
+
+#ifdef RT_OS_OS2
+# include <sys/socket.h>
+typedef int socklen_t;
+#endif
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/file.h>
+
+#include <VBox/log.h>
+
+
+static int fileGets(RTFILE File, void *pvBuf, size_t cbBufSize, size_t *pcbRead)
+{
+    size_t cbRead;
+    char bTest;
+    int rc = VERR_NO_MEMORY;
+    char *pu8Buf = (char *)pvBuf;
+    *pcbRead = 0;
+
+    while (   RT_SUCCESS(rc = RTFileRead(File, &bTest, 1, &cbRead))
+           && (pu8Buf - (char *)pvBuf) >= 0   
+           && (size_t)(pu8Buf - (char *)pvBuf) < cbBufSize)
+    {
+        if (cbRead == 0)
+            return VERR_EOF;
+
+        if (bTest == '\r' || bTest == '\n')
+        {
+            *pu8Buf = 0;
+            return VINF_SUCCESS;
+        }
+        *pu8Buf = bTest;
+         pu8Buf++;
+        (*pcbRead)++;
+    }
+    return rc;
+}
+
+
+HostDnsServiceResolvConf::HostDnsServiceResolvConf(const char* aResolvConfFilename)
+{
+    m_ResolvConfFilename = com::Utf8Str(aResolvConfFilename);
+}
+
+
+HostDnsServiceResolvConf::~HostDnsServiceResolvConf()
+{
+    m_ResolvConfFilename.setNull();
+    RTFileClose(m_ResolvConfFile);
+}
+
+HRESULT HostDnsServiceResolvConf::init()
+{
+    HRESULT hrc;
+
+    int rc = RTFileOpen(&m_ResolvConfFile, m_ResolvConfFilename.c_str(), 
+                        RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
+    AssertRCReturn(rc, E_FAIL);
+
+
+    hrc = HostDnsService::init();
+    AssertComRCReturn(hrc, hrc);
+
+
+
+    hrc = update();
+    AssertComRCReturn(hrc, hrc);
+
+    return S_OK;
+}
+
+
+HRESULT HostDnsServiceResolvConf::update()
+{
+    char buff[256];
+    char buff2[256];
+    int cNameserversFound = 0;
+    bool fWarnTooManyDnsServers = false;
+    struct in_addr tmp_addr;
+    int rc;
+    size_t bytes;
+
+    while (    RT_SUCCESS(rc = fileGets(m_ResolvConfFile, buff, sizeof(buff), &bytes))
+            && rc != VERR_EOF)
+    {
+        if (   cNameserversFound == 4
+            && !fWarnTooManyDnsServers
+            && sscanf(buff, "nameserver%*[ \t]%255s", buff2) == 1)
+        {
+            fWarnTooManyDnsServers = true;
+            LogRel(("NAT: too many nameservers registered.\n"));
+        }
+        if (   sscanf(buff, "nameserver%*[ \t]%255s", buff2) == 1
+            && cNameserversFound < 4) /* Unix doesn't accept more than 4 name servers*/
+        {
+            if (!inet_aton(buff2, &tmp_addr))
+                continue;
+
+	    m_llNameServers.push_back(com::Utf8Str(buff2));
+
+            cNameserversFound++;
+        }
+        if ((!strncmp(buff, "domain", 6) || !strncmp(buff, "search", 6)))
+        {
+            char *tok;
+            char *saveptr;
+
+            tok = strtok_r(&buff[6], " \t\n", &saveptr);
+	    
+	    if (tok != NULL)
+		m_DomainName = com::Utf8Str(tok);
+        }
+    }
+
+    if (!cNameserversFound)
+        return E_FAIL;
+
+    return S_OK;
+
+}
Index: /trunk/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp	(revision 48330)
+++ /trunk/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp	(revision 48330)
@@ -0,0 +1,183 @@
+/* $Id$ */
+/** @file
+ * Darwin specific DNS information fetching. 
+ */
+
+/*
+ * Copyright (C) 2004-2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <VBox/com/string.h>
+#include <VBox/com/ptr.h>
+
+#include "../HostDnsService.h"
+
+#include <iprt/err.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SCDynamicStore.h>
+
+
+
+SCDynamicStoreRef g_store;
+CFRunLoopSourceRef g_DnsWatcher;
+
+static const CFStringRef kStateNetworkGlobalDNSKey = CFSTR("State:/Network/Global/DNS");
+
+HostDnsServiceDarwin::HostDnsServiceDarwin(){}
+HostDnsServiceDarwin::~HostDnsServiceDarwin()
+{
+    CFRelease(g_DnsWatcher);
+    CFRelease(g_store);
+}
+
+void HostDnsServiceDarwin::hostDnsServiceStoreCallback(void *arg0, void *arg1, void *info)
+{
+    HostDnsServiceDarwin *pThis = (HostDnsServiceDarwin *)info;
+    
+    NOREF(arg0); /* SCDynamicStore */
+    NOREF(arg1); /* CFArrayRef */
+
+    RTCritSectEnter(&pThis->m_hCritSect);
+    pThis->update();
+    RTCritSectLeave(&pThis->m_hCritSect);
+}
+
+HRESULT HostDnsServiceDarwin::init()
+{
+    SCDynamicStoreContext ctx;
+    RT_ZERO(ctx);
+    
+    ctx.info = this;
+
+    g_store = SCDynamicStoreCreate(NULL, CFSTR("org.virtualbox.VBoxSVC"), 
+                                   (SCDynamicStoreCallBack)HostDnsServiceDarwin::hostDnsServiceStoreCallback, 
+                                   &ctx);
+    AssertReturn(g_store, E_FAIL);
+
+    g_DnsWatcher = SCDynamicStoreCreateRunLoopSource(NULL, g_store, 0);
+    if (!g_DnsWatcher)
+        return E_OUTOFMEMORY;
+
+    CFArrayRef watchingArrayRef = CFArrayCreate(NULL, 
+                                                (const void **)&kStateNetworkGlobalDNSKey, 
+                                                1, &kCFTypeArrayCallBacks);
+    if (!watchingArrayRef)
+    {
+        CFRelease(g_DnsWatcher);
+        return E_OUTOFMEMORY;
+    }
+
+    if(SCDynamicStoreSetNotificationKeys(g_store, watchingArrayRef, NULL))
+        CFRunLoopAddSource(CFRunLoopGetMain(), g_DnsWatcher, kCFRunLoopCommonModes);
+
+    CFRelease(watchingArrayRef);
+
+    HRESULT hrc = HostDnsService::init();
+    AssertComRCReturn(hrc, hrc);
+    
+    return update();
+}
+
+
+
+HRESULT HostDnsServiceDarwin::start()
+{
+    return S_OK;
+}
+
+
+void HostDnsServiceDarwin::stop()
+{
+}
+
+
+HRESULT HostDnsServiceDarwin::update()
+{
+    m_llNameServers.clear();
+    m_llSearchStrings.clear();
+    m_DomainName.setNull();
+
+    CFPropertyListRef propertyRef = SCDynamicStoreCopyValue(g_store, 
+                                                            kStateNetworkGlobalDNSKey);
+    /**
+     * 0:vvl@nb-mbp-i7-2(0)# scutil 
+     * > get State:/Network/Global/DNS
+     * > d.show
+     * <dictionary> {
+     * DomainName : vvl-domain
+     * SearchDomains : <array> {
+     * 0 : vvl-domain
+     * 1 : de.vvl-domain.com
+     * }
+     * ServerAddresses : <array> {
+     * 0 : 192.168.1.4
+     * 1 : 192.168.1.1
+     * 2 : 8.8.4.4
+     *   }
+     * }
+     */
+    
+    CFStringRef domainNameRef = (CFStringRef)CFDictionaryGetValue(
+      static_cast<CFDictionaryRef>(propertyRef), CFSTR("DomainName"));
+    if (domainNameRef)
+    {
+        const char *pszDomainName = CFStringGetCStringPtr(domainNameRef, 
+                                                    CFStringGetSystemEncoding());
+        if (pszDomainName)
+            m_DomainName = com::Utf8Str(pszDomainName);
+    }
+
+    int i, arrayCount;
+    CFArrayRef serverArrayRef = (CFArrayRef)CFDictionaryGetValue(
+      static_cast<CFDictionaryRef>(propertyRef), CFSTR("ServerAddresses"));
+    if (serverArrayRef)
+    {
+        arrayCount = CFArrayGetCount(serverArrayRef);
+        for (i = 0; i < arrayCount; ++i)
+        {
+            CFStringRef serverAddressRef = (CFStringRef)CFArrayGetValueAtIndex(serverArrayRef, i);
+            if (!serverArrayRef)
+                continue;
+
+            const char *pszServerAddress = CFStringGetCStringPtr(serverAddressRef, 
+                                                           CFStringGetSystemEncoding());
+            if (!pszServerAddress)
+                continue;
+            
+            m_llNameServers.push_back(com::Utf8Str(pszServerAddress));
+        }
+    }
+
+    CFArrayRef searchArrayRef = (CFArrayRef)CFDictionaryGetValue(
+      static_cast<CFDictionaryRef>(propertyRef), CFSTR("SearchDomains"));
+    if (searchArrayRef)
+    {
+        arrayCount = CFArrayGetCount(searchArrayRef);
+        
+        for (i = 0; i < arrayCount; ++i)
+        {
+            CFStringRef searchStringRef = (CFStringRef)CFArrayGetValueAtIndex(searchArrayRef, i);
+            if (!searchArrayRef)
+                continue;
+
+            const char *pszSearchString = CFStringGetCStringPtr(searchStringRef, 
+                                                          CFStringGetSystemEncoding());
+            if (!pszSearchString)
+                continue;
+            
+            m_llSearchStrings.push_back(com::Utf8Str(pszSearchString));
+        }
+    }
+
+    CFRelease(propertyRef);
+    return S_OK;
+}
Index: /trunk/src/VBox/Main/src-server/win/HostDnsServiceWin.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/win/HostDnsServiceWin.cpp	(revision 48330)
+++ /trunk/src/VBox/Main/src-server/win/HostDnsServiceWin.cpp	(revision 48330)
@@ -0,0 +1,153 @@
+/* -*- indent-tabs-mode: nil; -*- */
+#include <VBox/com/string.h>
+#include <VBox/com/ptr.h>
+
+#include "../HostDnsService.h"
+
+#include <iprt/assert.h>
+#include <iprt/err.h>
+
+#include <Windows.h>
+
+static HKEY g_hKeyTcpipParameters;
+
+HostDnsServiceWin::HostDnsServiceWin()
+{
+    RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
+		 TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), 
+		 0, KEY_READ, &g_hKeyTcpipParameters);
+}
+
+
+HostDnsServiceWin::~HostDnsServiceWin()
+{
+    if (!g_hKeyTcpipParameters)
+    {
+	RegCloseKey(g_hKeyTcpipParameters);
+        g_hKeyTcpipParameters = 0;
+    }
+}
+
+
+HRESULT HostDnsServiceWin::init(void)
+{
+    HRESULT hrc;
+    hrc = HostDnsService::init();
+    AssertComRCReturn(hrc, hrc);
+
+    hrc = update();
+    AssertComRCReturn(hrc, hrc);
+
+    return S_OK;
+}
+
+
+HRESULT HostDnsServiceWin::start(void)
+{
+    return S_OK;
+}
+
+
+void HostDnsServiceWin::stop(void)
+{
+}
+
+
+HRESULT HostDnsServiceWin::update()
+{
+    HRESULT hrc;
+    DWORD regIndex;
+    BYTE abDomain[256];
+    BYTE abNameServers[256];
+    BYTE abSearchList[256];
+
+    m_llNameServers.clear();
+    m_llSearchStrings.clear();
+    m_DomainName.setNull();
+
+    RT_ZERO(abDomain);
+    RT_ZERO(abNameServers);
+    RT_ZERO(abSearchList);
+    
+    regIndex = 0;
+    do {
+        CHAR keyName[256];
+        DWORD cbKeyName = 256;
+        DWORD keyType = 0;
+        BYTE keyData[1024];
+        DWORD cbKeyData = 1024;
+    
+        hrc = RegEnumValueA(g_hKeyTcpipParameters, regIndex, keyName, &cbKeyName, 0,
+                            &keyType, keyData, &cbKeyData);
+        if (   hrc == ERROR_SUCCESS 
+            || hrc == ERROR_MORE_DATA)
+        {
+            if (   RTStrICmp("Domain", keyName) == 0 
+                && cbKeyData > 1
+                && cbKeyData < 256)
+                memcpy(abDomain, keyData, cbKeyData);
+
+            else if (   RTStrICmp("DhcpDomain", keyName) == 0
+                     && cbKeyData > 1
+                     && abDomain[0] == 0
+                     && cbKeyData < 256)
+                memcpy(abDomain, keyData, cbKeyData);
+
+            else if (   RTStrICmp("NameServer", keyName) == 0 
+                     && cbKeyData > 1
+                     && cbKeyData < 256)
+                memcpy(abNameServers, keyData, cbKeyData);
+      
+            else if (   RTStrICmp("DhcpNameServer", keyName) == 0 
+                     && cbKeyData > 1
+                     && abNameServers[0] == 0
+                     && cbKeyData < 256)
+                memcpy(abNameServers, keyData, cbKeyData);
+
+            else if (   RTStrICmp("SearchList", keyName) == 0 
+                     && cbKeyData > 1
+                     && cbKeyData < 256)
+              memcpy(abSearchList, keyData, cbKeyData);
+        }
+        regIndex++;
+    } while (hrc != ERROR_NO_MORE_ITEMS);
+
+    /* OK, now parse and update DNS structures. */
+    /* domain name */
+    m_DomainName = com::Utf8Str((char *)abDomain);
+    /* server list */
+    strList2List(m_llNameServers, (char *)abNameServers);
+    /* search list */
+    strList2List(m_llSearchStrings, (char *)abNameServers);
+    
+    return S_OK;
+}
+
+
+
+void HostDnsServiceWin::strList2List(Utf8StrList& lst, char *strLst)
+{
+    char *next, *current;
+    char address[512];
+
+    AssertPtrReturnVoid(strLst);
+
+    if (strlen(strLst) == 0)
+      return;
+
+    current = strLst;
+    do {
+        RT_ZERO(address);
+        next = RTStrStr(current, " ");
+
+        if (next)
+          strncpy(address, current, next - current);
+        else
+          strcpy(address, current);
+
+        lst.push_back(com::Utf8Str(address));
+
+        current = next + 1;
+    } while(next);
+
+}
