Fix 1968248: "Opening of any other XML-file crashes synfigstudio". Attempting to...
[synfig.git] / synfig-core / trunk / src / synfig / loadcanvas.cpp
index 8c93e1e..cf01a8c 100644 (file)
@@ -121,46 +121,25 @@ static void _canvas_file_name_changed(Canvas *x)
 }
 
 Canvas::Handle
-synfig::open_canvas(const String &filename)
+synfig::open_canvas(const String &filename,String &errors)
 {
-       CanvasParser parser;
-
-       parser.set_allow_errors(true);
-
-       Canvas::Handle canvas=parser.parse_from_file(filename);
-
-       if(parser.error_count())
-               return Canvas::Handle();
-
-       return canvas;
+       return open_canvas_as(filename, filename, errors);
 }
 
 Canvas::Handle
-synfig::open_canvas_as(const String &filename,const String &as)
+synfig::open_canvas_as(const String &filename,const String &as,String &errors)
 {
        CanvasParser parser;
 
        parser.set_allow_errors(true);
 
-       Canvas::Handle canvas=parser.parse_from_file_as(filename,as);
-
-       if(parser.error_count())
-               return Canvas::Handle();
-
-       return canvas;
-}
-
-Canvas::Handle
-synfig::string_to_canvas(const String &data)
-{
-       CanvasParser parser;
-
-       parser.set_allow_errors(true);
-
-       Canvas::Handle canvas=parser.parse_from_string(data);
+       Canvas::Handle canvas=parser.parse_from_file_as(filename,as,errors);
 
        if(parser.error_count())
+       {
+               errors = parser.get_errors_text();
                return Canvas::Handle();
+       }
 
        return canvas;
 }
@@ -195,6 +174,7 @@ CanvasParser::error(xmlpp::Node *element, const String &text)
 {
        string str=strprintf("%s:<%s>:%d: error: ",filename.c_str(),element->get_name().c_str(),element->get_line())+text;
        total_errors_++;
+       errors_text += "  * " + str + "\n";
        if(!allow_errors_)
                throw runtime_error(str);
        cerr<<str<<endl;
@@ -1719,6 +1699,11 @@ CanvasParser::parse_layer(xmlpp::Element *element,Canvas::Handle canvas)
 
                        String param_name=child->get_attribute("name")->get_value();
 
+                       // SVN r2013 and r2014 renamed all 'pos' and 'offset' parameters to 'origin'
+                       // 'pos' and 'offset' will appear in old .sif files; handle them correctly
+                       if (param_name == "pos" || param_name == "offset")
+                               param_name = "origin";
+
                        if(child->get_attribute("use"))
                        {
                                // If the "use" attribute is used, then the
@@ -1879,10 +1864,20 @@ CanvasParser::parse_canvas(xmlpp::Element *element,Canvas::Handle parent,bool in
                canvas->set_version(parent->get_version());
 
        if(element->get_attribute("width"))
-               canvas->rend_desc().set_w(atoi(element->get_attribute("width")->get_value().c_str()));
+       {
+               int width = atoi(element->get_attribute("width")->get_value().c_str());
+               if (width < 1)
+                       fatal_error(element, _("Canvas with width or height less than one is not allowed"));
+               canvas->rend_desc().set_w(width);
+       }
 
        if(element->get_attribute("height"))
-               canvas->rend_desc().set_h(atoi(element->get_attribute("height")->get_value().c_str()));
+       {
+               int height = atoi(element->get_attribute("height")->get_value().c_str());
+               if (height < 1)
+                       fatal_error(element, _("Canvas with width or height less than one is not allowed"));
+               canvas->rend_desc().set_h(height);
+       }
 
        if(element->get_attribute("xres"))
                canvas->rend_desc().set_x_res(atof(element->get_attribute("xres")->get_value().c_str()));
@@ -2085,20 +2080,14 @@ CanvasParser::parse_canvas(xmlpp::Element *element,Canvas::Handle parent,bool in
 }
 
 Canvas::Handle
-CanvasParser::parse_from_file(const String &file)
+CanvasParser::parse_from_file_as(const String &file_,const String &as_,String &errors)
 {
-       return parse_from_file_as(file,file);
-}
+       ChangeLocale change_locale(LC_NUMERIC, "C");
+       String file(unix_to_local_path(file_));
+       String as(unix_to_local_path(as_));
 
-Canvas::Handle
-CanvasParser::parse_from_file_as(const String &file_,const String &as_)
-{
        try
        {
-        ChangeLocale change_locale(LC_NUMERIC, "C");
-               String file(unix_to_local_path(file_));
-               String as(unix_to_local_path(as_));
-
                if(get_open_canvas_map().count(etl::absolute_path(as)))
                        return get_open_canvas_map()[etl::absolute_path(as)];
 
@@ -2108,12 +2097,11 @@ CanvasParser::parse_from_file_as(const String &file_,const String &as_)
                if(parser)
                {
                        Canvas::Handle canvas(parse_canvas(parser.get_document()->get_root_node(),0,false,as));
+                       if (!canvas) return canvas;
                        get_open_canvas_map()[etl::absolute_path(as)]=canvas;
                        canvas->signal_deleted().connect(sigc::bind(sigc::ptr_fun(_remove_from_open_canvas_map),canvas.get()));
                        canvas->signal_file_name_changed().connect(sigc::bind(sigc::ptr_fun(_canvas_file_name_changed),canvas.get()));
 
-
-
                        const ValueNodeList& value_node_list(canvas->value_node_list());
 
                        again:
@@ -2136,67 +2124,24 @@ CanvasParser::parse_from_file_as(const String &file_,const String &as_)
        catch(Exception::FileNotFound) { synfig::error("FileNotFound Thrown"); }
        catch(Exception::IDNotFound) { synfig::error("IDNotFound Thrown"); }
        catch(Exception::IDAlreadyExists) { synfig::error("IDAlreadyExists Thrown"); }
-       catch(const std::exception& ex)
-       {
-               synfig::error("Standard Exception: "+String(ex.what()));
-               return Canvas::Handle();
-       }
-       catch(const String& str)
+       catch(xmlpp::internal_error x)
        {
-               cerr<<str<<endl;
-               //      synfig::error(str);
-               return Canvas::Handle();
+               printf("caught internal error\n");
+               if (!strcmp(x.what(), "Couldn't create parsing context"))
+                       throw runtime_error(String("  * ") + _("Can't open file") + " \"" + file + "\"");
+               throw;
        }
-       return Canvas::Handle();
-}
-
-Canvas::Handle
-CanvasParser::parse_from_string(const String &data)
-{
-       try
-       {
-        ChangeLocale change_locale(LC_NUMERIC, "C");
-               filename=_("<INTERNAL>");
-               total_warnings_=0;
-               xmlpp::DomParser parser;
-               parser.parse_memory(data);
-               xmlpp::Element *root=parser.get_document()->get_root_node();
-               if(parser)
-               {
-                       Canvas::Handle canvas(parse_canvas(root));
-                       canvas->signal_deleted().connect(sigc::bind(sigc::ptr_fun(_remove_from_open_canvas_map),canvas.get()));
-                       canvas->signal_file_name_changed().connect(sigc::bind(sigc::ptr_fun(_canvas_file_name_changed),canvas.get()));
-
-                       const ValueNodeList& value_node_list(canvas->value_node_list());
-                       again:
-                       ValueNodeList::const_iterator iter;
-                       for(iter=value_node_list.begin();iter!=value_node_list.end();++iter)
-                       {
-                               ValueNode::Handle value_node(*iter);
-                               if(value_node->is_exported() && value_node->get_id().find("Unnamed")==0)
-                               {
-                                       canvas->remove_value_node(value_node);
-                                       goto again;
-                               }
-                       }
-
-                       return canvas;
-               }
-       }
-       catch(Exception::BadLinkName) { synfig::error("BadLinkName Thrown"); }
-       catch(Exception::BadType) { synfig::error("BadType Thrown"); }
-       catch(Exception::FileNotFound) { synfig::error("FileNotFound Thrown"); }
-       catch(Exception::IDNotFound) { synfig::error("IDNotFound Thrown"); }
-       catch(Exception::IDAlreadyExists) { synfig::error("IDAlreadyExists Thrown"); }
        catch(const std::exception& ex)
        {
                synfig::error("Standard Exception: "+String(ex.what()));
+               errors = ex.what();
                return Canvas::Handle();
        }
        catch(const String& str)
        {
                cerr<<str<<endl;
                //      synfig::error(str);
+               errors = str;
                return Canvas::Handle();
        }
        return Canvas::Handle();