/* * Copyright (C) 2005-2008 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 * */ // NfoFile.cpp: implementation of the CNfoFile class. // ////////////////////////////////////////////////////////////////////// #include "NfoFile.h" #include "VideoDatabase.h" #include "utils/IMDB.h" #include "addons/AddonManager.h" #include "FileSystem/File.h" #include "FileSystem/Directory.h" #include "GUISettings.h" #include "Util.h" #include "FileItem.h" #include "Album.h" #include "Artist.h" #include "GUISettings.h" #include "LangInfo.h" #include "utils/log.h" #include using namespace XFILE; using namespace std; using namespace ADDON; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CNfoFile::CNfoFile() { m_doc = NULL; m_headofdoc = NULL; } CNfoFile::~CNfoFile() { Close(); } CNfoFile::NFOResult CNfoFile::Create(const CStdString& strPath, const ScraperPtr& info, int episode) { m_info = info; // assume we can use these settings m_type = ScraperTypeFromContent(info->Content()); if (FAILED(Load(strPath))) return NO_NFO; CFileItemList items; bool bNfo=false; AddonPtr addon; ScraperPtr defaultScraper; if (!CAddonMgr::Get().GetDefault(m_type, addon)) return NO_NFO; else defaultScraper = boost::dynamic_pointer_cast(addon); if (m_type == ADDON_SCRAPER_ALBUMS) { CAlbum album; bNfo = GetDetails(album); } else if (m_type == ADDON_SCRAPER_ARTISTS) { CArtist artist; bNfo = GetDetails(artist); } else if (m_type == ADDON_SCRAPER_TVSHOWS || m_type == ADDON_SCRAPER_MOVIES || m_type == ADDON_SCRAPER_MUSICVIDEOS) { // first check if it's an XML file with the info we need CVideoInfoTag details; bNfo = GetDetails(details); if (episode > -1 && bNfo && m_type == ADDON_SCRAPER_TVSHOWS) { int infos=0; while (m_headofdoc && details.m_iEpisode != episode) { m_headofdoc = strstr(m_headofdoc+1,""); bNfo = GetDetails(details); infos++; } if (details.m_iEpisode != episode) { bNfo = false; details.Reset(); m_headofdoc = m_doc; if (infos == 1) // still allow differing nfo/file numbers for single ep nfo's bNfo = GetDetails(details); } } } // Get Selected Scraper CVideoDatabase database; database.Open(); ADDON::ScraperPtr selected = database.GetScraperForPath(strPath); database.Close(); vector vecScrapers; // add selected scraper if (selected) vecScrapers.push_back(selected); if (g_guiSettings.GetBool("scrapers.langfallback")) { VECADDONS addons; CAddonMgr::Get().GetAddons(m_type,addons); for (unsigned i=0;iID().Equals(selected->ID()) || addons[i]->ID().Equals(defaultScraper->ID())) continue; ScraperPtr scraper = boost::dynamic_pointer_cast(addons[i]); // skip if scraper requires settings and there's nothing set yet if (scraper->RequiresSettings() && !scraper->HasUserSettings()) continue; // add same language, multi-language and music scrapers if (scraper->Language().Equals(g_langInfo.GetDVDSubtitleLanguage()) || scraper->Language().Equals("multi") || scraper->Supports(CONTENT_ARTISTS) || scraper->Supports(CONTENT_ALBUMS)) { vecScrapers.push_back(scraper); } } } // add default scraper if ((selected && selected->ID() != defaultScraper->ID()) || !selected) vecScrapers.push_back(defaultScraper); // search .. int res = -1; for (unsigned int i=0;i 0) ? COMBINED_NFO:FULL_NFO; return (m_strImDbUrl.size() > 0) ? URL_NFO : NO_NFO; } bool CNfoFile::DoScrape(ScraperPtr& scraper) { vector extras; extras.push_back(m_doc); CScraperUrl url; CFileCurl http; vector xml = scraper->Run("NfoUrl",url,http,&extras); for (vector::iterator it = xml.begin(); it != xml.end(); ++it) { TiXmlDocument doc; doc.Parse(it->c_str()); if (doc.RootElement()) { if (stricmp(doc.RootElement()->Value(),"error")==0) { CIMDB::ShowErrorDialog(doc.RootElement()); return false; } TiXmlElement* pId = doc.FirstChildElement("id"); if (pId && pId->FirstChild()) m_strImDbNr = pId->FirstChild()->Value(); } } return true; } int CNfoFile::Scrape(ScraperPtr& scraper, const CStdString& strURL /* = "" */) { if (scraper->Type() != m_type) { return 1; } if (!scraper->Load()) return 0; // init and clear cache scraper->ClearCache(); vector extras; CScraperUrl url; CFileCurl http; if (strURL.IsEmpty()) { extras.push_back(m_doc); vector result = scraper->Run("NfoScrape",url,http,&extras); if (!result.empty()) { TiXmlDocument doc; doc.Parse(m_strImDbUrl.c_str()); if (doc.RootElement() && doc.RootElement()->FirstChildElement()) { CVideoInfoTag details; if (GetDetails(details,m_strImDbUrl.c_str())) { Close(); m_size = m_strImDbUrl.size(); m_doc = new char[m_size+1]; m_headofdoc = m_doc; strcpy(m_doc,m_strImDbUrl.c_str()); return 0; } } if (!DoScrape(scraper)) return 2; } if (m_strImDbUrl.size() > 0) return 0; else return 1; } else // we check to identify the episodeguide url { extras.push_back(strURL); vector result = scraper->Run("EpisodeGuideUrl",url,http,&extras); if (result.empty() || result[0].IsEmpty()) return 1; return 0; } } int CNfoFile::Load(const CStdString& strFile) { Close(); XFILE::CFile file; if (file.Open(strFile)) { m_size = (int)file.GetLength(); try { m_doc = new char[m_size+1]; m_headofdoc = m_doc; } catch (...) { CLog::Log(LOGERROR, "%s: Exception while creating file buffer",__FUNCTION__); return 1; } if (!m_doc) { file.Close(); return 1; } file.Read(m_doc, m_size); m_doc[m_size] = 0; file.Close(); return 0; } return 1; } void CNfoFile::Close() { if (m_doc != NULL) { delete m_doc; m_doc = 0; } m_size = 0; }