2 * Copyright (C) 2005-2008 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "XBMSDirectory.h"
23 #include "SectionLoader.h"
26 #include "utils/CharsetConverter.h"
27 #include "utils/URIUtils.h"
29 using namespace XFILE;
33 #include "libXBMS/ccincludes.h"
34 #include "libXBMS/ccbuffer.h"
35 #include "libXBMS/ccxclient.h"
36 #include "libXBMS/ccxmltrans.h"
40 struct DiscoveryCallbackContext
47 static void DiscoveryCallback(const char *addr, const char *port, const char *version,
48 const char *comment, void *context);
50 CXBMSDirectory::CXBMSDirectory(void)
52 CSectionLoader::Load("LIBXBMS");
55 CXBMSDirectory::~CXBMSDirectory(void)
57 CSectionLoader::Unload("LIBXBMS");
60 bool CXBMSDirectory::GetDirectory(const CStdString& strPathUtf8, CFileItemList &items)
63 char *filename, *fileinfo;
65 CStdString strPath=strPathUtf8;
66 g_charsetConverter.utf8ToStringCharset(strPath);
70 CStdString strRoot = strPath;
71 URIUtils::AddSlashAtEnd(strPath);
73 CcXstreamServerConnection conn = 0;
75 if (strPath == "xbms://")
77 if (url.GetFileName() == "")
79 int iOldSize=items.Size();
80 // Let's do the automatic discovery.
81 struct DiscoveryCallbackContext dc_context;
82 CStdString strPassword = url.GetPassWord();
83 CStdString strUserName = url.GetUserName();
85 dc_context.items = &items;
86 dc_context.username = ((strUserName.c_str() != NULL) && (strlen(strUserName.c_str()) > 0)) ? strUserName.c_str() : NULL;
87 dc_context.password = ((strPassword.c_str() != NULL) && (strlen(strPassword.c_str()) > 0)) ? strPassword.c_str() : NULL;
88 ccx_client_discover_servers(DiscoveryCallback, (void *)(&dc_context));
90 return (items.Size()>iOldSize);
94 if (cc_xstream_client_connect(url.GetHostName().c_str(),
95 (url.HasPort()) ? url.GetPort() : 1400, &conn) != CC_XSTREAM_CLIENT_OK)
97 if (conn != 0) cc_xstream_client_disconnect(conn);
102 if (cc_xstream_client_version_handshake(conn) != CC_XSTREAM_CLIENT_OK)
104 if (conn != 0) cc_xstream_client_disconnect(conn);
109 // Authenticate here!
110 CStdString strPassword = url.GetPassWord();
111 CStdString strUserName = url.GetUserName();
112 if (strPassword.size() && strUserName.size())
114 // We don't check the return value here. If authentication
115 // step fails, let's try if server lets us log in without
117 cc_xstream_client_password_authenticate(conn,
119 strPassword.c_str() );
121 CStdString strFileName = url.GetFileName();
124 if (cc_xstream_client_setcwd(conn, "/") == CC_XSTREAM_CLIENT_OK)
126 CStdString strFile = url.GetFileName();
127 for (int i = 0; i < (int)strFile.size(); ++i)
129 if (strFile[i] == '/' || strFile[i] == '\\')
133 if (cc_xstream_client_setcwd(conn, strDir.c_str()) != CC_XSTREAM_CLIENT_OK)
135 if (conn != 0) cc_xstream_client_disconnect(conn);
143 strDir += strFile[i];
149 if (conn != 0) cc_xstream_client_disconnect(conn);
152 if (strDir.size() > 0)
154 if (cc_xstream_client_setcwd(conn, strDir.c_str()) != CC_XSTREAM_CLIENT_OK)
156 if (conn != 0) cc_xstream_client_disconnect(conn);
162 if (cc_xstream_client_dir_open(conn, &handle) != CC_XSTREAM_CLIENT_OK)
164 if (conn != 0) cc_xstream_client_disconnect(conn);
169 while (cc_xstream_client_dir_read(conn, handle, &filename, &fileinfo) == CC_XSTREAM_CLIENT_OK)
171 if (*filename == '\0')
177 bool bIsDirectory = false;
179 if (strstr(fileinfo, "<ATTRIB>directory</ATTRIB>"))
182 CStdString strLabel=filename;
183 g_charsetConverter.unknownToUTF8(strLabel);
184 CFileItemPtr pItem(new CFileItem(strLabel));
186 char* pstrSizeStart = strstr(fileinfo, "<SIZE>");
187 char* pstrSizeEnd = strstr(fileinfo, "</SIZE>");
188 if (pstrSizeStart && pstrSizeEnd)
191 pstrSizeStart += strlen("<SIZE>");
192 strncpy(szSize, pstrSizeStart, pstrSizeEnd - pstrSizeStart);
193 szSize[pstrSizeEnd - pstrSizeStart] = 0;
194 pItem->m_dwSize = _atoi64(szSize);
197 char* pstrModificationStart = strstr(fileinfo, "<MODIFICATION>");
198 char* pstrModificationEnd = strstr(fileinfo, "</MODIFICATION>");
199 if (pstrModificationStart && pstrModificationEnd)
201 char szModification[128];
202 pstrModificationStart += strlen("<MODIFICATION>");
203 strncpy(szModification, pstrModificationStart, pstrModificationEnd - pstrModificationStart);
204 szModification[pstrModificationEnd - pstrModificationStart] = 0;
205 int64_t lTimeDate = _atoi64(szModification);
207 FILETIME fileTime, localTime;
208 LONGLONG ll = Int32x32To64(lTimeDate, 10000000) + 116444736000000000LL;
209 fileTime.dwLowDateTime = (DWORD) (ll & 0xFFFFFFFF);
210 fileTime.dwHighDateTime = (DWORD)(ll >> 32);
212 FileTimeToLocalFileTime(&fileTime, &localTime);
213 pItem->m_dateTime=localTime;
218 pItem->m_strPath = strRoot;
219 pItem->m_strPath += filename;
220 g_charsetConverter.unknownToUTF8(pItem->m_strPath);
221 pItem->m_bIsFolder = bIsDirectory;
222 if (pItem->m_bIsFolder)
223 URIUtils::AddSlashAtEnd(pItem->m_strPath);
230 cc_xstream_client_close_all(conn);
233 cc_xstream_client_disconnect(conn);
238 static void DiscoveryCallback(const char *addr, const char *port, const char *version,
239 const char *comment, void *context)
241 struct DiscoveryCallbackContext *c = (struct DiscoveryCallbackContext *)context;
244 CStdString itemName = "Server: ";
245 CStdString strPath = "xbms://";
248 if (strcmp(port, "1400") != 0)
250 itemName += " Port: ";
253 if (strlen(comment) > 0)
261 if (c->username != NULL)
263 strPath += c->username;
264 if (c->password != NULL)
267 strPath += c->password;
277 g_charsetConverter.unknownToUTF8(itemName);
278 CFileItemPtr pItem(new CFileItem(itemName));
279 pItem->m_strPath = strPath;
280 g_charsetConverter.unknownToUTF8(pItem->m_strPath);
281 pItem->m_bIsFolder = true;
282 pItem->m_bIsShareOrDrive = true;
283 pItem->SetIconImage("DefaultNetwork.png");
284 c->items->Add(pItem);
286 bool CXBMSDirectory::Exists(const char* strPath)
289 CStdString strPath2(strPath);
290 if (GetDirectory(strPath2,items))