rebase-hrefs.cpp revision c0537dcfe264414d52ad86579d57cb0cb2183dcb
#include "xml/rebase-hrefs.h"
#include "dir-util.h"
#include "../document.h" /* Unfortunately there's a separate xml/document.h. */
#include "sp-object.h"
#include "streq.h"
#include "xml/attribute-record.h"
#include <glib.h>
#include <glibmm/miscutils.h>
#include <glibmm/uriutils.h>
/**
* Determine if a href needs rebasing.
*/
{
bool ret = true;
ret = false;
/* False (no change) is the right behaviour even when the base URI differs from the
* document URI: RFC 3986 defines empty string relative URL as referring to the containing
* document, rather than referring to the base URI. */
} else {
/* Don't change data or http hrefs. */
/* Assume it shouldn't be changed. This is probably wrong if the scheme is `file'
* (or if the scheme of the new base is non-file, though I believe that never
* happens at the time of writing), but that's rare, and we won't try too hard to
* handle this now: wait until after the freeze, then add liburiparser (or similar)
* as a dependency and do it properly. For now we'll just try to be simple (while
* at least still correctly handling data hrefs). */
ret = false;
/* If absolute then keep it as is.
*
* Even in the following borderline cases:
*
* - We keep it absolute even if it is in new_base (directly or indirectly).
*
* - We assume that if xlink:href is absolute then we honour it in preference to
* sodipodi:absref even if sodipodi:absref points to an existing file while xlink:href
* doesn't. This is because we aren't aware of any bugs in xlink:href handling when
* it's absolute, so we assume that it's the best value to use even in this case.)
*/
/* No strong preference on what we do for sodipodi:absref. Once we're
* confident of our handling of xlink:href and xlink:base, we should clear it.
* Though for the moment we do the simple thing: neither clear nor set it. */
ret = false;
}
}
return ret;
}
{
if ( sp_absref
{
/* sodipodi:absref points to an existing file while xlink:href doesn't.
* This could mean that xlink:href is wrong, or it could mean that the user
* intends to supply the missing file later.
*
* Given that we aren't sure what the right behaviour is, and given that a
* wrong xlink:href value may mean a bug (as has occurred in the past), we
* write a message to stderr. */
g_warning("xlink:href points to non-existent file, so using sodipodi:absref instead");
/* Currently, we choose to use sodipodi:absref in this situation (because we
* aren't yet confident in xlink:href interpretation); though note that
* honouring a foreign attribute in preference to standard SVG xlink:href and
* xlink:base means that we're not a conformant SVG user agent, so eventually
* we hope to have enough confidence in our xlink:href and xlink:base handling
* to be able to disregard sodipodi:absref.
*
* effic: Once we no longer consult sodipodi:absref, we can do
* `if (base unchanged) { return; }' at the start of rebase_hrefs.
*/
}
return ret;
}
gchar const *const new_abs_base,
{
if (old_abs_base == new_abs_base) {
return attributes;
}
/* First search attributes for xlink:href and sodipodi:absref, putting the rest in ret.
*
* However, if we find that xlink:href doesn't need rebasing, then return immediately
* with no change to attributes. */
{
if (!href_needs_rebasing(static_cast<char const *>(old_href))) {
return attributes;
}
} else {
}
}
}
if (!old_href) {
return attributes;
/* We could instead return ret in this case, i.e. ensure that sodipodi:absref is cleared if
* no xlink:href attribute. However, retaining it might be more cautious.
*
* (For the usual case of not present, attributes and ret will be the same except
* reversed.) */
}
ret = cons(AttributeRecord(href_key, share_string(new_href.c_str())), ret); // Check if this is safe/copied or if it is only held.
if (sp_absref) {
/* We assume that if there wasn't previously a sodipodi:absref attribute
* then we shouldn't create one. */
ret);
}
return ret;
}
// std::string Inkscape::XML::rebase_href_attrs( std::string const &oldAbsBase, std::string const &newAbsBase, gchar const * /*href*/, gchar const */*absref*/ )
// {
// std::string ret;
// //g_message( "XX need to flip from [%s] to [%s]", oldAbsBase.c_str(), newAbsBase.c_str() );
// if ( oldAbsBase != newAbsBase ) {
// }
// return ret;
// }
{
/* Note that we don't currently try to handle the case of doc_base containing
* `..' or `.' path components. This non-handling means that sometimes
* sp_relative_path_from_path will needlessly give an absolute path.
*
* It's probably not worth trying to address this until we're using proper
*
* (Note that one possibile difficulty with `..' is symlinks.) */
if (!doc_base) {
} else {
}
return ret;
}
void Inkscape::XML::rebase_hrefs(SPDocument *const doc, gchar const *const new_base, bool const spns)
{
return;
}
/* TODO: Should handle not just image but also:
*
* a, altGlyph, animElementAttrs, animate, animateColor, animateMotion, animateTransform,
* animation, audio, color-profile, cursor, definition-src, discard, feImage, filter,
* font-face-uri, foreignObject, glyphRef, handler, linearGradient, mpath, pattern,
* prefetch, radialGradient, script, set, textPath, tref, use, video
*
* (taken from the union of the xlink:href elements listed at
*
* Also possibly some other attributes of type <URI> or <IRI> or list-thereof, or types like
* special case. xlink:role and xlink:arcrole can be assumed to be already absolute, based on
* http://www.w3.org/TR/SVG11/struct.html#xlinkRefAttrs .)
*
* Note that it may not useful to set sodipodi:absref for anything other than image.
*
* Note also that Inkscape only supports fragment hrefs (href="#pattern257") for many of these
* cases. */
{
if ( !tmp ) {
continue;
}
}
}
// The following two cases are for absolute hrefs that can be converted to relative.
// Imported images, first time rebased, need an old base.
}
// Files moved from a absolute path need a new one.
}
// Other bitmaps are either really absolute, or already relative.
#ifdef WIN32
/* Windows relative path needs their native separators before we
* compare it to native baserefs. */
}
#endif
/* TODO: Most of this function currently treats href as if it were a simple filename
* (e.g. passing it to g_path_is_absolute, g_build_filename or IO::file_test, or avoiding
* changing non-file hrefs), which breaks if href starts with a scheme or if href contains
* any escaping. */
if ( href_needs_rebasing(href) ) {
/* todo: One difficult case once we support writing to non-file locations is where
* existing hrefs in the document point to local files. In this case, we should
* probably copy those referenced files to the new location at the same time. It's
* less clear what to do when copying from one non-file location to another. We may
* need to ask the user in some way (even if it's as a checkbox), but we'd like to
* bother the user as little as possible yet also want to warn the user about the case
* of file hrefs. */
: NULL ));
#ifdef WIN32
/* Native Windows path separators are replaced with / so that the href
#endif
} else {
}
/* impl: I assume that if !spns then any existing sodipodi:absref is about to get
* cleared (or is already cleared) anyway, in which case it doesn't matter whether we
* clear or leave any existing sodipodi:absref value. If that assumption turns out to
* be wrong, then leaving it means risking leaving the wrong value (if xlink:href
* referred to a different file than sodipodi:absref) while clearing it means risking
* losing information. */
}
}
}
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vi: set autoindent shiftwidth=4 tabstop=8 filetype=cpp expandtab softtabstop=4 encoding=utf-8 textwidth=99 :