/** * Doku see wxFileSystemHandler */ wxString wxChmFSHandler::FindFirst(const wxString& spec, int flags) { wxString right = GetRightLocation(spec); wxString left = GetLeftLocation(spec); wxString nativename = wxFileSystem::URLToFileName(left).GetFullPath(); if ( GetProtocol(left) != _T("file") ) { wxLogError(_("CHM handler currently supports only local files!")); return wxEmptyString; } m_chm = new wxChmTools(wxFileName(nativename)); m_pattern = right.AfterLast(_T('/')); wxString m_found = m_chm->Find(m_pattern); // now fake around hhp-files which are not existing in projects... if (m_found.empty() && m_pattern.Contains(_T(".hhp")) && !m_pattern.Contains(_T(".hhp.cached"))) { m_found.Printf(_T("%s#chm:%s.hhp"), left.c_str(), m_pattern.BeforeLast(_T('.')).c_str()); } return m_found; }
wxString wxArchiveFSHandler::FindFirst(const wxString& spec, int flags) { wxString right = GetRightLocation(spec); wxString left = GetLeftLocation(spec); wxString protocol = GetProtocol(spec); wxString key = left + wxT("#") + protocol + wxT(":"); if (!right.empty() && right.Last() == wxT('/')) right.RemoveLast(); if (!m_cache) m_cache = new wxArchiveFSCache; const wxArchiveClassFactory *factory; factory = wxArchiveClassFactory::Find(protocol); if (!factory) return wxEmptyString; m_Archive = m_cache->Get(key); if (!m_Archive) { wxFSFile *leftFile = m_fs.OpenFile(left); if (!leftFile) return wxEmptyString; m_Archive = m_cache->Add(key, *factory, leftFile->DetachStream()); delete leftFile; } m_FindEntry = NULL; switch (flags) { case wxFILE: m_AllowDirs = false, m_AllowFiles = true; break; case wxDIR: m_AllowDirs = true, m_AllowFiles = false; break; default: m_AllowDirs = m_AllowFiles = true; break; } m_ZipFile = key; m_Pattern = right.AfterLast(wxT('/')); m_BaseDir = right.BeforeLast(wxT('/')); if (m_BaseDir.StartsWith(wxT("/"))) m_BaseDir = m_BaseDir.Mid(1); if (m_Archive) { if (m_AllowDirs) { delete m_DirsFound; m_DirsFound = new wxArchiveFilenameHashMap(); if (right.empty()) // allow "/" to match the archive root return spec; } return DoFind(); } return wxEmptyString; }
wxFSFile* wxChmFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location) { wxString right = GetRightLocation(location); wxString left = GetLeftLocation(location); wxInputStream *s; int index; if ( GetProtocol(left) != _T("file") ) { wxLogError(_("CHM handler currently supports only local files!")); return NULL; } // Work around javascript wxString tmp = wxString(right); if ( tmp.MakeLower().Contains(_T("javascipt")) && tmp.Contains(_T("\'")) ) { right = right.AfterFirst(_T('\'')).BeforeLast(_T('\'')); } // now work on the right location if (right.Contains(_T(".."))) { wxFileName abs(right); abs.MakeAbsolute(_T("/")); right = abs.GetFullPath(); } // a workaround for absolute links to root if ( (index=right.Index(_T("//"))) != wxNOT_FOUND ) { right=wxString(right.Mid(index+1)); wxLogWarning(_("Link contained '//', converted to absolute link.")); } wxFileName leftFilename = wxFileSystem::URLToFileName(left); // Open a stream to read the content of the chm-file s = new wxChmInputStream(leftFilename.GetFullPath(), right, true); wxString mime = GetMimeTypeFromExt(location); if ( s ) { return new wxFSFile(s, left + _T("#chm:") + right, mime, GetAnchor(location), wxDateTime(wxFileModificationTime(left))); } delete s; return NULL; }
wxFSFile* wxZipFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location) { wxString right = GetRightLocation(location); wxString left = GetLeftLocation(location); wxZipInputStream *s; if (right.Contains(wxT("./"))) { if (right.GetChar(0) != wxT('/')) right = wxT('/') + right; wxFileName rightPart(right, wxPATH_UNIX); rightPart.Normalize(wxPATH_NORM_DOTS, wxT("/"), wxPATH_UNIX); right = rightPart.GetFullPath(wxPATH_UNIX); } if (right.GetChar(0) == wxT('/')) right = right.Mid(1); // a new wxFileSystem object is needed here to avoid infinite recursion wxFSFile *leftFile = wxFileSystem().OpenFile(left); if (!leftFile) return NULL; s = new wxZipFSInputStream(leftFile); if (s && s->IsOk()) { bool found = false; while (!found) { wxZipEntry *ent = s->GetNextEntry(); if (!ent) break; if (ent->GetInternalName() == right) found = true; delete ent; } if (found) return new wxFSFile(s, left + wxT("#zip:") + right, GetMimeTypeFromExt(location), GetAnchor(location) #if wxUSE_DATETIME , wxDateTime(wxFileModificationTime(left)) #endif // wxUSE_DATETIME ); } delete s; return NULL; }
wxString wxZipFSHandler::FindFirst(const wxString& spec, int flags) { wxString right = GetRightLocation(spec); wxString left = GetLeftLocation(spec); if (!right.empty() && right.Last() == wxT('/')) right.RemoveLast(); if (m_Archive) { delete m_Archive; m_Archive = NULL; } switch (flags) { case wxFILE: m_AllowDirs = false, m_AllowFiles = true; break; case wxDIR: m_AllowDirs = true, m_AllowFiles = false; break; default: m_AllowDirs = m_AllowFiles = true; break; } m_ZipFile = left; wxFSFile *leftFile = wxFileSystem().OpenFile(left); if (leftFile) m_Archive = new wxZipFSInputStream(leftFile); m_Pattern = right.AfterLast(wxT('/')); m_BaseDir = right.BeforeLast(wxT('/')); if (m_BaseDir.StartsWith(wxT("/"))) m_BaseDir = m_BaseDir.Mid(1); if (m_Archive) { if (m_AllowDirs) { delete m_DirsFound; m_DirsFound = new wxZipFilenameHashMap(); if (right.empty()) // allow "/" to match the archive root return spec; } return DoFind(); } return wxEmptyString; }
wxFSFile* wxFilterFSHandler::OpenFile( wxFileSystem& fs, const wxString& location) { wxString right = GetRightLocation(location); if (!right.empty()) return NULL; wxString protocol = GetProtocol(location); const wxFilterClassFactory *factory = wxFilterClassFactory::Find(protocol); if (!factory) return NULL; wxString left = GetLeftLocation(location); wxFSFilePtr leftFile(fs.OpenFile(left)); if (!leftFile.get()) return NULL; wxInputStreamPtr leftStream(leftFile->DetachStream()); if (!leftStream.get() || !leftStream->IsOk()) return NULL; wxInputStreamPtr stream(factory->NewStream(leftStream.release())); // The way compressed streams are supposed to be served is e.g.: // Content-type: application/postscript // Content-encoding: gzip // So the mime type should be just the mime type of the lhs. However check // whether the mime type is that of this compression format (e.g. // application/gzip). If so pop any extension and try GetMimeTypeFromExt, // e.g. if it were '.ps.gz' pop the '.gz' and try looking up '.ps' wxString mime = leftFile->GetMimeType(); if (factory->CanHandle(mime, wxSTREAM_MIMETYPE)) mime = GetMimeTypeFromExt(factory->PopExtension(left)); return new wxFSFile(stream.release(), left + wxT("#") + protocol + wxT(":") + right, mime, GetAnchor(location) #if wxUSE_DATETIME , leftFile->GetModificationTime() #endif // wxUSE_DATETIME ); }
wxString LeftLocation(const wxString& p) { return GetLeftLocation(p); }
wxFSFile* wxArchiveFSHandler::OpenFile( wxFileSystem& WXUNUSED(fs), const wxString& location) { wxString right = GetRightLocation(location); wxString left = GetLeftLocation(location); wxString protocol = GetProtocol(location); wxString key = left + wxT("#") + protocol + wxT(":"); if (right.Contains(wxT("./"))) { if (right.GetChar(0) != wxT('/')) right = wxT('/') + right; wxFileName rightPart(right, wxPATH_UNIX); rightPart.Normalize(wxPATH_NORM_DOTS, wxT("/"), wxPATH_UNIX); right = rightPart.GetFullPath(wxPATH_UNIX); } if (right.GetChar(0) == wxT('/')) right = right.Mid(1); if (!m_cache) m_cache = new wxArchiveFSCache; const wxArchiveClassFactory *factory; factory = wxArchiveClassFactory::Find(protocol); if (!factory) return NULL; wxArchiveFSCacheData *cached = m_cache->Get(key); if (!cached) { wxFSFile *leftFile = m_fs.OpenFile(left); if (!leftFile) return NULL; cached = m_cache->Add(key, *factory, leftFile->DetachStream()); delete leftFile; } wxArchiveEntry *entry = cached->Get(right); if (!entry) return NULL; wxInputStream *leftStream = cached->NewStream(); if (!leftStream) { wxFSFile *leftFile = m_fs.OpenFile(left); if (!leftFile) return NULL; leftStream = leftFile->DetachStream(); delete leftFile; } wxArchiveInputStream *s = factory->NewStream(leftStream); if ( !s ) return NULL; s->OpenEntry(*entry); if (!s->IsOk()) { delete s; return NULL; } #if WXWIN_COMPATIBILITY_2_6 && wxUSE_ZIPSTREAM if (factory->IsKindOf(CLASSINFO(wxZipClassFactory))) ((wxZipInputStream*)s)->m_allowSeeking = true; #endif // WXWIN_COMPATIBILITY_2_6 return new wxFSFile(s, key + right, wxEmptyString, GetAnchor(location) #if wxUSE_DATETIME , entry->GetDateTime() #endif // wxUSE_DATETIME ); }
bool wxChmFSHandler::CanOpen(const wxString& location) { wxString p = GetProtocol(location); return (p == _T("chm")) && (GetProtocol(GetLeftLocation(location)) == _T("file")); }