Code changes to make external python work in windows. Changes credit to WiSo
[vuplus_xbmc] / xbmc / filesystem / XBMSDirectory.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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
19  *
20  */
21
22 #include "XBMSDirectory.h"
23 #include "SectionLoader.h"
24 #include "URL.h"
25 #include "FileItem.h"
26 #include "utils/CharsetConverter.h"
27 #include "utils/URIUtils.h"
28
29 using namespace XFILE;
30
31 extern "C"
32 {
33 #include "libXBMS/ccincludes.h"
34 #include "libXBMS/ccbuffer.h"
35 #include "libXBMS/ccxclient.h"
36 #include "libXBMS/ccxmltrans.h"
37 }
38
39
40 struct DiscoveryCallbackContext
41 {
42   CFileItemList *items;
43   const char *username;
44   const char *password;
45 };
46
47 static void DiscoveryCallback(const char *addr, const char *port, const char *version,
48                               const char *comment, void *context);
49
50 CXBMSDirectory::CXBMSDirectory(void)
51 {
52   CSectionLoader::Load("LIBXBMS");
53 }
54
55 CXBMSDirectory::~CXBMSDirectory(void)
56 {
57   CSectionLoader::Unload("LIBXBMS");
58 }
59
60 bool CXBMSDirectory::GetDirectory(const CStdString& strPathUtf8, CFileItemList &items)
61 {
62   unsigned long handle;
63   char *filename, *fileinfo;
64
65   CStdString strPath=strPathUtf8;
66   g_charsetConverter.utf8ToStringCharset(strPath);
67
68   CURL url(strPath);
69
70   CStdString strRoot = strPath;
71   URIUtils::AddSlashAtEnd(strPath);
72
73   CcXstreamServerConnection conn = 0;
74
75   if (strPath == "xbms://")
76   {
77     if (url.GetFileName() == "")
78     {
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();
84
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));
89
90       return (items.Size()>iOldSize);
91     }
92   }
93
94   if (cc_xstream_client_connect(url.GetHostName().c_str(),
95                                 (url.HasPort()) ? url.GetPort() : 1400, &conn) != CC_XSTREAM_CLIENT_OK)
96   {
97     if (conn != 0) cc_xstream_client_disconnect(conn);
98
99     return false;
100   }
101
102   if (cc_xstream_client_version_handshake(conn) != CC_XSTREAM_CLIENT_OK)
103   {
104     if (conn != 0) cc_xstream_client_disconnect(conn);
105
106     return false;
107   }
108
109   // Authenticate here!
110   CStdString strPassword = url.GetPassWord();
111   CStdString strUserName = url.GetUserName();
112   if (strPassword.size() && strUserName.size())
113   {
114     // We don't check the return value here.  If authentication
115     // step fails, let's try if server lets us log in without
116     // authentication.
117     cc_xstream_client_password_authenticate(conn,
118                                             strUserName.c_str(),
119                                             strPassword.c_str() );
120   }
121   CStdString strFileName = url.GetFileName();
122   CStdString strDir;
123   strDir = "";
124   if (cc_xstream_client_setcwd(conn, "/") == CC_XSTREAM_CLIENT_OK)
125   {
126     CStdString strFile = url.GetFileName();
127     for (int i = 0; i < (int)strFile.size(); ++i)
128     {
129       if (strFile[i] == '/' || strFile[i] == '\\')
130       {
131         if (strDir != "")
132         {
133           if (cc_xstream_client_setcwd(conn, strDir.c_str()) != CC_XSTREAM_CLIENT_OK)
134           {
135             if (conn != 0) cc_xstream_client_disconnect(conn);
136             return false;
137           }
138         }
139         strDir = "";
140       }
141       else
142       {
143         strDir += strFile[i];
144       }
145     }
146   }
147   else
148   {
149     if (conn != 0) cc_xstream_client_disconnect(conn);
150     return false;
151   }
152   if (strDir.size() > 0)
153   {
154     if (cc_xstream_client_setcwd(conn, strDir.c_str()) != CC_XSTREAM_CLIENT_OK)
155     {
156       if (conn != 0) cc_xstream_client_disconnect(conn);
157
158       return false;
159     }
160   }
161
162   if (cc_xstream_client_dir_open(conn, &handle) != CC_XSTREAM_CLIENT_OK)
163   {
164     if (conn != 0) cc_xstream_client_disconnect(conn);
165
166     return false;
167   }
168
169   while (cc_xstream_client_dir_read(conn, handle, &filename, &fileinfo) == CC_XSTREAM_CLIENT_OK)
170   {
171     if (*filename == '\0')
172     {
173       free(filename);
174       free(fileinfo);
175       break;
176     }
177     bool bIsDirectory = false;
178
179     if (strstr(fileinfo, "<ATTRIB>directory</ATTRIB>"))
180       bIsDirectory = true;
181
182     CStdString strLabel=filename;
183     g_charsetConverter.unknownToUTF8(strLabel);
184     CFileItemPtr pItem(new CFileItem(strLabel));
185
186     char* pstrSizeStart = strstr(fileinfo, "<SIZE>");
187     char* pstrSizeEnd = strstr(fileinfo, "</SIZE>");
188     if (pstrSizeStart && pstrSizeEnd)
189     {
190       char szSize[128];
191       pstrSizeStart += strlen("<SIZE>");
192       strncpy(szSize, pstrSizeStart, pstrSizeEnd - pstrSizeStart);
193       szSize[pstrSizeEnd - pstrSizeStart] = 0;
194       pItem->m_dwSize = _atoi64(szSize);
195     }
196
197     char* pstrModificationStart = strstr(fileinfo, "<MODIFICATION>");
198     char* pstrModificationEnd = strstr(fileinfo, "</MODIFICATION>");
199     if (pstrModificationStart && pstrModificationEnd)
200     {
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);
206
207       FILETIME fileTime, localTime;
208       LONGLONG ll = Int32x32To64(lTimeDate, 10000000) + 116444736000000000LL;
209       fileTime.dwLowDateTime = (DWORD) (ll & 0xFFFFFFFF);
210       fileTime.dwHighDateTime = (DWORD)(ll >> 32);
211
212       FileTimeToLocalFileTime(&fileTime, &localTime);
213       pItem->m_dateTime=localTime;
214
215     }
216
217
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);
224
225     items.Add(pItem);
226
227     free(filename);
228     free(fileinfo);
229   }
230   cc_xstream_client_close_all(conn);
231
232   if (conn != 0)
233     cc_xstream_client_disconnect(conn);
234
235   return true;
236 }
237
238 static void DiscoveryCallback(const char *addr, const char *port, const char *version,
239                               const char *comment, void *context)
240 {
241   struct DiscoveryCallbackContext *c = (struct DiscoveryCallbackContext *)context;
242
243   //Construct name
244   CStdString itemName = "Server: ";
245   CStdString strPath = "xbms://";
246   itemName += addr;
247
248   if (strcmp(port, "1400") != 0)
249   {
250     itemName += " Port: ";
251     itemName += port;
252   }
253   if (strlen(comment) > 0)
254   {
255     itemName += " (";
256     itemName += comment;
257     itemName += ")";
258   }
259
260   // Construct URL
261   if (c->username != NULL)
262   {
263     strPath += c->username;
264     if (c->password != NULL)
265     {
266       strPath += ":";
267       strPath += c->password;
268     }
269     strPath += "@";
270   }
271   strPath += addr;
272   strPath += ":";
273   strPath += port;
274   strPath += "/";
275
276   // Add to items
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);
285 }
286 bool CXBMSDirectory::Exists(const char* strPath)
287 {
288   CFileItemList items;
289   CStdString strPath2(strPath);
290   if (GetDirectory(strPath2,items))
291     return true;
292
293   return false;
294 }
295