Skip to content
This repository has been archived by the owner on Sep 30, 2018. It is now read-only.

Commit

Permalink
[droid] add apk handler for vfs
Browse files Browse the repository at this point in the history
  • Loading branch information
theuni committed Jun 2, 2012
1 parent fb83e5b commit b4648b1
Show file tree
Hide file tree
Showing 15 changed files with 597 additions and 6 deletions.
6 changes: 6 additions & 0 deletions xbmc/FileItem.cpp
Expand Up @@ -625,6 +625,7 @@ bool CFileItem::IsFileFolder() const
return (
IsSmartPlayList() ||
(IsPlayList() && g_advancedSettings.m_playlistAsFolders) ||
IsAPK() ||
IsZIP() ||
IsRAR() ||
IsRSS() ||
Expand Down Expand Up @@ -717,6 +718,11 @@ bool CFileItem::IsRAR() const
return URIUtils::IsRAR(m_strPath);
}

bool CFileItem::IsAPK() const
{
return URIUtils::IsAPK(m_strPath);
}

bool CFileItem::IsZIP() const
{
return URIUtils::IsZIP(m_strPath);
Expand Down
1 change: 1 addition & 0 deletions xbmc/FileItem.h
Expand Up @@ -113,6 +113,7 @@ class CFileItem :
bool IsDVDFile(bool bVobs = true, bool bIfos = true) const;
bool IsBDFile() const;
bool IsRAR() const;
bool IsAPK() const;
bool IsZIP() const;
bool IsCBZ() const;
bool IsCBR() const;
Expand Down
25 changes: 21 additions & 4 deletions xbmc/URL.cpp
Expand Up @@ -97,9 +97,14 @@ void CURL::Parse(const CStdString& strURL1)
// example: filename /foo/bar.zip/alice.rar/bob.avi
// This should turn into zip://rar:///foo/bar.zip/alice.rar/bob.avi
iPos = 0;
bool is_apk = (strURL.Find(".apk/", iPos) > 0);
while (1)
{
iPos = strURL.Find(".zip/", iPos);
if (is_apk)
iPos = strURL.Find(".apk/", iPos);
else
iPos = strURL.Find(".zip/", iPos);

int extLen = 3;
if (iPos < 0)
{
Expand All @@ -119,8 +124,16 @@ void CURL::Parse(const CStdString& strURL1)
#endif
{
Encode(archiveName);
CURL c((CStdString)"zip" + "://" + archiveName + '/' + strURL.Right(strURL.size() - iPos - 1));
*this = c;
if (is_apk)
{
CURL c((CStdString)"apk" + "://" + archiveName + '/' + strURL.Right(strURL.size() - iPos - 1));
*this = c;
}
else
{
CURL c((CStdString)"zip" + "://" + archiveName + '/' + strURL.Right(strURL.size() - iPos - 1));
*this = c;
}
return;
}
}
Expand Down Expand Up @@ -169,6 +182,7 @@ void CURL::Parse(const CStdString& strURL1)
|| strProtocol2.Equals("plugin")
|| strProtocol2.Equals("hdhomerun")
|| strProtocol2.Equals("rtsp")
|| strProtocol2.Equals("apk")
|| strProtocol2.Equals("zip"))
sep = "?;#|";
else if(strProtocol2.Equals("ftp")
Expand Down Expand Up @@ -469,7 +483,10 @@ const CStdString& CURL::GetProtocolOptions() const
const CStdString CURL::GetFileNameWithoutPath() const
{
// *.zip and *.rar store the actual zip/rar path in the hostname of the url
if ((m_strProtocol == "rar" || m_strProtocol == "zip") && m_strFileName.IsEmpty())
if ((m_strProtocol == "rar" ||
m_strProtocol == "zip" ||
m_strProtocol == "apk") &&
m_strFileName.IsEmpty())
return URIUtils::GetFileName(m_strHostName);

// otherwise, we've already got the filepath, so just grab the filename portion
Expand Down
1 change: 1 addition & 0 deletions xbmc/Util.cpp
Expand Up @@ -1255,6 +1255,7 @@ CStdString CUtil::ValidatePath(const CStdString &path, bool bFixDoubleSlashes /*
// recurse and crash XBMC
if (URIUtils::IsURL(path) &&
(path.Find('%') >= 0 ||
path.Left(4).Equals("apk:") ||
path.Left(4).Equals("zip:") ||
path.Left(4).Equals("rar:") ||
path.Left(6).Equals("stack:") ||
Expand Down
119 changes: 119 additions & 0 deletions xbmc/filesystem/APKDirectory.cpp
@@ -0,0 +1,119 @@
/*
* Copyright (C) 2012 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/

#include "APKDirectory.h"
#include "FileAPK.h"
#include "FileItem.h"
#include "utils/CharsetConverter.h"
#include "utils/log.h"
#include "utils/URIUtils.h"

#include <zip.h>

using namespace XFILE;

// Android apk directory i/o. Depends on libzip
// Basically the same format as zip.
// We might want to refactor CZipDirectory someday...
//////////////////////////////////////////////////////////////////////
bool CAPKDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
{
// uses a <fully qualified path>/filename.apk/...
CURL url(strPath);

CStdString path = url.GetFileName();
CStdString host = url.GetHostName();
URIUtils::AddSlashAtEnd(path);

// host name might be encoded rfc1738.txt, decode it.
CURL::Decode(host);

int zip_flags = 0, zip_error = 0, dir_marker = 0;
struct zip *zip_archive;
zip_archive = zip_open(host.c_str(), zip_flags, &zip_error);
if (!zip_archive || zip_error)
{
CLog::Log(LOGERROR, "CAPKDirectory::GetDirectory: Unable to open archive : '%s'",
host.c_str());
return false;
}

CStdString test_name;
int numFiles = zip_get_num_files(zip_archive);
for (int zip_index = 0; zip_index < numFiles; zip_index++)
{
test_name = zip_get_name(zip_archive, zip_index, zip_flags);

// check for non matching path.
if (!test_name.Left(path.size()).Equals(path))
continue;

// libzip does not index folders, only filenames. We search for a /,
// add it if it's not in our list already, and hope that no one has
// any "file/name.exe" files in a zip.

dir_marker = test_name.Find('/', path.size() + 1);
if (dir_marker > 0)
{
// return items relative to path
test_name=test_name.Left(dir_marker);

if (items.Contains(host + "/" + test_name))
continue;
}

struct zip_stat sb;
zip_stat_init(&sb);
if (zip_stat_index(zip_archive, zip_index, zip_flags, &sb) != -1)
{
g_charsetConverter.unknownToUTF8(test_name);
CFileItemPtr pItem(new CFileItem(test_name));
pItem->m_dwSize = sb.size;
pItem->m_dateTime = sb.mtime;
pItem->m_bIsFolder = dir_marker > 0 ;
pItem->SetPath(host + "/" + test_name);
pItem->SetLabel(test_name.Right(test_name.size() - path.size()));
items.Add(pItem);
}
}
zip_close(zip_archive);

return true;
}

bool CAPKDirectory::ContainsFiles(const CStdString& strPath)
{
// TODO: why might we need this ?
return false;
}

DIR_CACHE_TYPE CAPKDirectory::GetCacheType(const CStdString& strPath) const
{
return DIR_CACHE_ALWAYS;
}

bool CAPKDirectory::Exists(const char* strPath)
{
// uses a <fully qualified path>/filename.apk/...
CFileAPK apk;
CURL url(strPath);
return apk.Exists(url);
}
37 changes: 37 additions & 0 deletions xbmc/filesystem/APKDirectory.h
@@ -0,0 +1,37 @@
#pragma once
/*
* Copyright (C) 2012 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/

#include "IFileDirectory.h"

namespace XFILE
{
class CAPKDirectory : public IFileDirectory
{
public:
CAPKDirectory() {};
virtual ~CAPKDirectory() {};
virtual bool GetDirectory(const CStdString& strPath, CFileItemList &items);
virtual bool ContainsFiles(const CStdString& strPath);
virtual DIR_CACHE_TYPE GetCacheType(const CStdString& strPath) const;
virtual bool Exists(const char* strPath);
};
}
6 changes: 6 additions & 0 deletions xbmc/filesystem/DirectoryFactory.cpp
Expand Up @@ -76,6 +76,9 @@
#ifdef HAS_FILESYSTEM_HTSP
#include "HTSPDirectory.h"
#endif
#if defined(TARGET_ANDROID)
#include "APKDirectory.h"
#endif
#include "ZipDirectory.h"
#ifdef HAS_FILESYSTEM_RAR
#include "RarDirectory.h"
Expand Down Expand Up @@ -131,6 +134,9 @@ IDirectory* CDirectoryFactory::Create(const CStdString& strPath)
#endif
if (strProtocol == "udf") return new CUDFDirectory();
if (strProtocol == "plugin") return new CPluginDirectory();
#if defined(TARGET_ANDROID)
if (strProtocol == "apk") return new CAPKDirectory();
#endif
if (strProtocol == "zip") return new CZipDirectory();
#ifdef HAS_FILESYSTEM_RAR
if (strProtocol == "rar") return new CRarDirectory();
Expand Down
4 changes: 3 additions & 1 deletion xbmc/filesystem/File.cpp
Expand Up @@ -85,7 +85,7 @@ bool CFile::Cache(const CStdString& strFileName, const CStdString& strDest, XFIL

// special case for zips - ignore caching
CURL url(strFileName);
if (URIUtils::IsInZIP(strFileName))
if (URIUtils::IsInZIP(strFileName) || URIUtils::IsInAPK(strFileName))
url.SetOptions("?cache=no");
if (file.Open(url.Get(), READ_TRUNCATED))
{
Expand Down Expand Up @@ -218,6 +218,8 @@ bool CFile::Open(const CStdString& strFileName, unsigned int flags)
{
bool bPathInCache;
CURL url2(strFileName);
if (url2.GetProtocol() == "apk")
url2.SetOptions("");
if (url2.GetProtocol() == "zip")
url2.SetOptions("");
if (!g_directoryCache.FileExists(url2.Get(), bPathInCache) )
Expand Down

0 comments on commit b4648b1

Please sign in to comment.