23#include <com/sun/star/document/XExtendedFilterDetection.hpp>
24#include <com/sun/star/frame/Desktop.hpp>
25#include <com/sun/star/util/URLTransformer.hpp>
26#include <com/sun/star/util/XURLTransformer.hpp>
28#include <com/sun/star/io/XInputStream.hpp>
29#include <com/sun/star/io/XSeekable.hpp>
30#include <com/sun/star/task/XInteractionHandler.hpp>
41#define DEBUG_TYPE_DETECTION 0
43#if DEBUG_TYPE_DETECTION
60 {
"com.sun.star.document.TypeDetection" },
80 css::uno::Reference< css::util::XURLTransformer > xParser( css::util::URLTransformer::create(
m_xContext) );
81 xParser->parseStrict(
aURL);
88 cache.detectFlatForURL(
aURL, lFlatTypes);
91 (lFlatTypes.empty() ) &&
96 cache.detectFlatForURL(
aURL, lFlatTypes);
100 if (!lFlatTypes.empty())
129int getFlatTypeRank(std::u16string_view rType)
133 static const char* ranks[] = {
146 "writerglobal8_template",
148 "writerweb8_writer_template",
152 "writer_OOXML_Text_Template",
154 "writer_MS_Word_2007_Template",
155 "writer_MS_Word_2007",
156 "Office Open XML Spreadsheet Template",
157 "Office Open XML Spreadsheet",
158 "MS Excel 2007 XML Template",
160 "MS PowerPoint 2007 XML Template",
161 "MS PowerPoint 2007 XML AutoPlay",
162 "MS PowerPoint 2007 XML",
165 "Unified_Office_Format_text",
166 "Unified_Office_Format_spreadsheet",
167 "Unified_Office_Format_presentation",
170 "calc_StarOffice_XML_Calc",
171 "calc_StarOffice_XML_Calc_Template",
172 "chart_StarOffice_XML_Chart",
173 "draw_StarOffice_XML_Draw",
174 "draw_StarOffice_XML_Draw_Template",
175 "impress_StarOffice_XML_Impress",
176 "impress_StarOffice_XML_Impress_Template",
177 "math_StarOffice_XML_Math",
178 "writer_StarOffice_XML_Writer",
179 "writer_StarOffice_XML_Writer_Template",
180 "writer_globaldocument_StarOffice_XML_Writer_GlobalDocument",
181 "writer_web_StarOffice_XML_Writer_Web_Template",
184 "pdf_Portable_Document_Format",
187 "writer_T602_Document",
188 "writer_WordPerfect_Document",
189 "writer_MS_Works_Document",
190 "writer_MS_Word_97_Vorlage",
192 "writer_MS_Word_95_Vorlage",
194 "writer_MS_WinWord_60",
195 "writer_MS_WinWord_5",
196 "MS Excel 2007 Binary",
197 "calc_MS_Excel_97_VorlageTemplate",
199 "calc_MS_Excel_95_VorlageTemplate",
201 "calc_MS_Excel_5095_VorlageTemplate",
202 "calc_MS_Excel_5095",
203 "calc_MS_Excel_40_VorlageTemplate",
205 "calc_Pocket_Excel_File",
206 "impress_MS_PowerPoint_97_Vorlage",
207 "impress_MS_PowerPoint_97_AutoPlay",
208 "impress_MS_PowerPoint_97",
216 "emf_MS_Windows_Metafile",
217 "wmf_MS_Windows_Metafile",
219 "svm_StarView_Metafile",
221 "tif_Tag_Image_File",
222 "tga_Truevision_TARGA",
223 "sgf_StarOffice_Writer_SGF",
224 "ras_Sun_Rasterfile",
225 "psd_Adobe_Photoshop",
226 "png_Portable_Network_Graphic",
229 "gif_Graphics_Interchange",
231 "pcx_Zsoft_Paintbrush",
234 "pcd_Photo_CD_Base4",
235 "pcd_Photo_CD_Base16",
237 "impress_CGM_Computer_Graphics_Metafile",
238 "draw_WordPerfect_Graphics",
239 "draw_Visio_Document",
240 "draw_Publisher_Document",
241 "draw_Corel_Presentation_Exchange",
242 "draw_CorelDraw_Document",
243 "writer_LotusWordPro_Document",
244 "writer_MIZI_Hwp_97",
247 "writer_ODT_FlatXML",
249 "impress_ODP_FlatXML",
251 "calc_ADO_rowset_XML",
252 "calc_MS_Excel_2003_XML",
253 "writer_MS_Word_2003_XML",
254 "writer_DocBook_File",
256 "svg_Scalable_Vector_Graphics",
257 "math_MathML_XML_Math",
260 "dxf_AutoCAD_Interchange",
261 "eps_Encapsulated_PostScript",
262 "pbm_Portable_Bitmap",
263 "ppm_Portable_Pixelmap",
264 "pgm_Portable_Graymap",
267 "writer_Rich_Text_Format",
268 "writer_web_HTML_help",
277 "writer_layout_dump_xml",
278 "writer_indexing_export",
282 "StarBaseReportChart",
287 size_t n = std::size(ranks);
289 for (
size_t i = 0;
i <
n; ++
i)
307 bool operator() (
const FlatDetectionInfo& r1,
const FlatDetectionInfo& r2)
const
309 if (r1.bMatchByPattern != r2.bMatchByPattern)
310 return r1.bMatchByPattern;
312 if (r1.bMatchByExtension != r2.bMatchByExtension)
313 return r1.bMatchByExtension;
315 int rank1 = getFlatTypeRank(r1.sType);
316 int rank2 = getFlatTypeRank(r2.sType);
319 return rank1 > rank2;
321 if (r1.bPreselectedByDocumentService != r2.bPreselectedByDocumentService)
322 return r1.bPreselectedByDocumentService;
325 return r1.sType > r2.sType;
331 bool operator() (
const FlatDetectionInfo& r1,
const FlatDetectionInfo& r2)
const
333 return r1.sType > r2.sType;
339 bool operator() (
const FlatDetectionInfo& r1,
const FlatDetectionInfo& r2)
const
341 return r1.sType == r2.sType;
349 explicit FindByType(OUString aType) :
maType(
std::move(aType)) {}
350 bool operator() (
const FlatDetectionInfo& rInfo)
const
352 return rInfo.sType ==
maType;
356#if DEBUG_TYPE_DETECTION
357void printFlatDetectionList(
const char* caption,
const FlatDetection& types)
359 cout <<
"-- " << caption <<
" (size=" << types.size() <<
")" <<
endl;
360 for (
auto const& item : types)
362 cout <<
" type='" << item.sType <<
"'; match by extension (" << item.bMatchByExtension
363 <<
"); match by pattern (" << item.bMatchByPattern <<
"); pre-selected by doc service ("
364 << item.bPreselectedByDocumentService <<
")" <<
endl;
366 cout <<
"--" <<
endl;
377 OUString
sType, sURL;
387#if OSL_DEBUG_LEVEL > 0
388 if (stlDescriptor.find(
"FileName" ) != stlDescriptor.end())
389 OSL_FAIL(
"Detect using of deprecated and already unsupported MediaDescriptor property \"FileName\"!");
393 aURL.Complete = sURL;
394 css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(
m_xContext));
395 xParser->parseStrict(
aURL);
397 OUString aSelectedFilter = stlDescriptor.getUnpackedValueOrDefault(
399 if (!aSelectedFilter.isEmpty())
414 std::stable_sort(lFlatTypes.begin(), lFlatTypes.end(), SortByPriority());
415 auto last = std::unique(lFlatTypes.begin(), lFlatTypes.end(), EqualByType());
416 lFlatTypes.erase(
last, lFlatTypes.end());
418 OUString sLastChance;
427 if (!lFlatTypes.empty())
442 OSL_FAIL(
"set first flat detected type without a registered deep detection service as \"last chance\" ... nevertheless some other deep detections said \"NO\". I TRY IT!");
446 catch(
const css::uno::RuntimeException&)
450 catch(
const css::uno::Exception&)
461 stlDescriptor >> lDescriptor;
471 OUString sFilter = rDescriptor.getUnpackedValueOrDefault(
474 if (!sFilter.isEmpty())
489 OUString sRealType =
sType;
499 css::beans::NamedValue lIProps[] {
507 for (
auto const&
filter : lFilters)
514 sal_Int32 nFlags = 0;
519 if (
static_cast<SfxFilterFlags>(nFlags) & SfxFilterFlags::PREFERED)
522 catch(
const css::uno::Exception&) {}
527 if (!sFilter.isEmpty())
535 catch(
const css::uno::Exception&)
558 catch(
const css::uno::Exception&)
571 css::beans::NamedValue lIProps[] {
575 for (
auto const&
filter : lFilters)
582 sal_Int32 nFlags = 0;
588 catch(
const css::uno::Exception&)
594 if (!sFilter.isEmpty())
601 catch(
const css::uno::Exception&)
607 std::unique_lock<std::mutex>& ,
608 const OUString& sPreSelType,
const util::URL& aParsedURL,
FlatDetection& rFlatTypes,
bool bDocService)
614 bool bBreakDetection =
false;
618 bool bMatchByPattern =
false;
622 bool bMatchByExtension =
false;
625 OUString
sType(sPreSelType);
631 catch(
const css::container::NoSuchElementException&)
634 bBreakDetection =
true;
637 if (!bBreakDetection)
641 if ( aParsedURL.Complete ==
"private:stream" )
642 bBreakDetection =
true;
645 if (!bBreakDetection)
652 sExtension = sExtension.toAsciiLowerCase();
656 const css::uno::Sequence<OUString> lExtensions = aType[
PROPNAME_EXTENSIONS].get<css::uno::Sequence<OUString> >();
657 const css::uno::Sequence<OUString> lURLPattern = aType[
PROPNAME_URLPATTERN].get<css::uno::Sequence<OUString> >();
659 for (
auto const& extension : lExtensions)
661 OUString sCheckExtension(extension.toAsciiLowerCase());
662 if (sCheckExtension == sExtension)
664 bBreakDetection =
true;
665 bMatchByExtension =
true;
670 if (!bBreakDetection)
672 for (
auto const& elem : lURLPattern)
675 if (aCheck.
Matches(aParsedURL.Main))
677 bMatchByPattern =
true;
685 if (!
sType.isEmpty())
687 FlatDetection::iterator it = std::find_if(rFlatTypes.begin(), rFlatTypes.end(), FindByType(
sType));
688 if (it != rFlatTypes.end())
690 if (bMatchByExtension)
691 it->bMatchByExtension =
true;
693 it->bMatchByPattern =
true;
695 it->bPreselectedByDocumentService =
true;
706 std::unique_lock<std::mutex>& rGuard,
707 const OUString& sPreSelDocumentService,
const util::URL& aParsedURL,
FlatDetection& rFlatTypes)
710 std::vector<OUString> lFilters;
719 css::beans::NamedValue lIProps[] {
723 catch (
const css::container::NoSuchElementException&)
733 for (
auto const&
filter : lFilters)
750 catch (
const container::NoSuchElementException&)
761 std::unique_lock<std::mutex>& rGuard,
767 std::vector<OUString> aFilterNames;
774 catch (
const container::NoSuchElementException&)
780 for (
auto const& filterName : aFilterNames)
789 rFlatTypes.push_back(aInfo);
796 for (
auto const& elem : aFlatByURL)
798 FlatDetection::iterator itPos = std::find_if(rFlatTypes.begin(), rFlatTypes.end(), FindByType(elem.sType));
799 if (itPos == rFlatTypes.end())
801 rFlatTypes.push_back(elem);
818 std::stable_sort(rFlatTypes.begin(), rFlatTypes.end(), SortByType());
819 auto last = std::unique(rFlatTypes.begin(), rFlatTypes.end(), EqualByType());
820 rFlatTypes.erase(
last, rFlatTypes.end());
824 if (!sSelectedType.isEmpty())
829 if (!sSelectedDoc.isEmpty())
837 OUString& rLastChance )
858 for (
auto const& flatTypeInfo : lFlatTypes)
862 OUString sFlatType = flatTypeInfo.sType;
870 (flatTypeInfo.bMatchByPattern)
883 OUString sDetectService;
887 if (sDetectService.isEmpty())
893 if (rLastChance.isEmpty())
894 rLastChance = sFlatType;
902 if (!sDeepType.isEmpty())
905 catch(
const css::container::NoSuchElementException&)
918 css::uno::Reference< css::io::XInputStream >
xStream = rDescriptor.getUnpackedValueOrDefault(
920 css::uno::Reference< css::io::XInputStream >());
921 css::uno::Reference< css::io::XSeekable > xSeek(
xStream, css::uno::UNO_QUERY);
929 catch(
const css::uno::RuntimeException&)
933 catch(
const css::uno::Exception&)
952 css::uno::Reference< css::document::XExtendedFilterDetection > xDetector;
953 css::uno::Reference< css::uno::XComponentContext > xContext;
971 xContext->getServiceManager()->createInstanceWithContext(sDetectService, xContext),
972 css::uno::UNO_QUERY_THROW);
978 if ( ! xDetector.is())
992 css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
993 rDescriptor >> lDescriptor;
994 sDeepType = xDetector->detect(lDescriptor);
995 rDescriptor << lDescriptor;
1027 css::uno::Reference< css::task::XInteractionHandler > xInteraction =
1029 css::uno::Reference< css::task::XInteractionHandler >());
1031 if (!xInteraction.is())
1038 css::uno::Reference< css::io::XInputStream >
xStream =
1040 css::uno::Reference< css::io::XInputStream >());
1048 (sURL.isEmpty() ) ||
1050 (sURL.equalsIgnoreAsciiCase(
"private:stream"))
1057 ::framework::RequestFilterSelect aRequest(sURL);
1058 xInteraction->handle(aRequest.GetRequest());
1061 if (aRequest.isAbort())
1070 OUString sFilter = aRequest.getFilter();
1077 catch(
const css::uno::Exception&)
1086 bool bSuccess =
false;
1098 throw css::uno::Exception(
1099 "Could not open stream for <" + sURL +
">",
1102 if ( !bRequestedReadOnly )
1117 if (pItType != rDescriptor.end())
1118 rDescriptor.erase(pItType);
1119 if (pItFilter != rDescriptor.end())
1120 rDescriptor.erase(pItFilter);
1125 const OUString& sType )
1140 const OUString& sFilter )
1154 catch(
const css::container::NoSuchElementException&){}
1163extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1165 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any>
const&)
Reference< XComponentContext > m_xContext
constexpr OUStringLiteral sDocumentService
OUString getExtension(sal_Int32 nIndex=LAST_SEGMENT, bool bIgnoreFinalSlash=true, DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
bool Matches(std::u16string_view rStr) const
void init(const OUString &sImplementationName, const css::uno::Sequence< OUString > &lServiceNames, FilterCache::EItemType eType)
initialize this generic instance with some specialized values from our derived object.
represent an item of a FilterCache instance.
void detectFlatForURL(const css::util::URL &aURL, FlatDetection &rFlatTypes) const
supports a flat type detection for given URL.
CacheItem getItem(EItemType eType, const OUString &sItem)
return an item, which match the specified type and name.
implements the service <type scope="com.sun.star.document">TypeDetection</type>.
static void impl_getPreselectionForDocumentService(std::unique_lock< std::mutex > &rGuard, const OUString &sPreSelDocumentService, const css::util::URL &aParsedURL, FlatDetection &rFlatTypes)
TypeDetection(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
standard ctor to connect this interface wrapper to the global filter cache instance ....
OUString impl_askDetectService(const OUString &sDetectService, utl::MediaDescriptor &rDescriptor)
make deep type detection for a specified detect service (threadsafe!).
void impl_checkResultsAndAddBestFilter(utl::MediaDescriptor &rDescriptor, OUString &sType)
search the best suitable filter for the given type and add it into the media descriptor.
static void impl_getAllFormatTypes(std::unique_lock< std::mutex > &rGuard, const css::util::URL &aParsedURL, utl::MediaDescriptor const &rDescriptor, FlatDetection &rFlatTypes)
Get all format types that we handle.
static bool impl_validateAndSetTypeOnDescriptor(utl::MediaDescriptor &rDescriptor, const OUString &sType)
validate the specified type and its relationships and set all needed information related to this type...
rtl::Reference< TerminateDetection > m_xTerminateListener
static OUString impl_askUserForTypeAndFilterIfAllowed(utl::MediaDescriptor &rDescriptor)
try to find an interaction handler and ask him to select a possible filter for this unknown format.
static void impl_seekStreamToZero(utl::MediaDescriptor const &rDescriptor)
seek a might existing stream to position 0.
static OUString impl_getTypeFromFilter(std::unique_lock< std::mutex > &rGuard, const OUString &rFilterName)
static void impl_removeTypeFilterFromDescriptor(utl::MediaDescriptor &rDescriptor)
remove anything related to a TYPE/FILTER entry from the specified MediaDescriptor.
virtual OUString SAL_CALL queryTypeByURL(const OUString &sURL) override
void impl_openStream(utl::MediaDescriptor &rDescriptor)
check if an input stream is already part of the given MediaDescriptor and creates a new one if necess...
virtual ~TypeDetection() override
standard dtor.
css::uno::Reference< css::uno::XComponentContext > m_xContext
virtual OUString SAL_CALL queryTypeByDescriptor(css::uno::Sequence< css::beans::PropertyValue > &lDescriptor, sal_Bool bAllowDeep) override
OUString impl_detectTypeFlatAndDeep(utl::MediaDescriptor &rDescriptor, const FlatDetection &lFlatTypes, bool bAllowDeep, OUString &rLastChance)
make a combined flat/deep type detection
static bool impl_getPreselectionForType(std::unique_lock< std::mutex > &rGuard, const OUString &sPreSelType, const css::util::URL &aParsedURL, FlatDetection &rFlatTypes, bool bDocService)
static bool impl_validateAndSetFilterOnDescriptor(utl::MediaDescriptor &rDescriptor, const OUString &sFilter)
validate the specified filter and its relationships and set all needed information related to this fi...
constexpr OUStringLiteral PROPNAME_FLAGS
constexpr OUStringLiteral PROPNAME_PREFERREDFILTER
constexpr OUStringLiteral PROPNAME_DETECTSERVICE
constexpr OUStringLiteral PROPNAME_TYPE
used to identify a filter item property against the configuration API and can be used at all name con...
constexpr OUStringLiteral PROPNAME_URLPATTERN
constexpr OUStringLiteral PROPNAME_DOCUMENTSERVICE
constexpr OUStringLiteral PROPNAME_EXTENSIONS
#define TOOLS_WARN_EXCEPTION(area, stream)
Shape IDs per cluster in DGG atom.
COMPHELPER_DLLPUBLIC bool isFileUrl(std::u16string_view url)
::std::vector< FlatDetectionInfo > FlatDetection
FilterCache & GetTheFilterCache()
constexpr OUStringLiteral last
bool equalsAscii(std::u16string_view s1, std::string_view s2)
TOOLS_DLLPUBLIC SvStream & endl(SvStream &rStr)
is used to collect all matching types of a URL during type detection.
bool bPreselectedByDocumentService
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * filter_TypeDetection_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)