]> git.donarmstrong.com Git - flightcrew.git/blob - src/FlightCrew/Validators/Ncx/ContentTargetsPresent.cpp
Imported Upstream version 0.7.2+dfsg
[flightcrew.git] / src / FlightCrew / Validators / Ncx / ContentTargetsPresent.cpp
1 /************************************************************************\r
2 **\r
3 **  Copyright (C) 2010  Strahinja Markovic\r
4 **\r
5 **  This file is part of FlightCrew.\r
6 **\r
7 **  FlightCrew is free software: you can redistribute it and/or modify\r
8 **  it under the terms of the GNU Lesser General Public License as published\r
9 **  by the Free Software Foundation, either version 3 of the License, or\r
10 **  (at your option) any later version.\r
11 **\r
12 **  FlightCrew is distributed in the hope that it will be useful,\r
13 **  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 **  GNU Lesser General Public License for more details.\r
16 **\r
17 **  You should have received a copy of the GNU Lesser General Public License\r
18 **  along with FlightCrew.  If not, see <http://www.gnu.org/licenses/>.\r
19 **\r
20 *************************************************************************/\r
21 \r
22 #include <stdafx.h>\r
23 #include "ContentTargetsPresent.h"\r
24 #include <FromXercesStringConverter.h>\r
25 #include <XmlUtils.h>\r
26 #include "Misc/Utilities.h"\r
27 \r
28 namespace FlightCrew\r
29 {\r
30 \r
31 std::vector< Result > ContentTargetsPresent::ValidateXml( \r
32     const xc::DOMDocument &document,\r
33     const fs::path &filepath )\r
34 {\r
35     std::vector< Result > results;\r
36     std::vector< ContentTargetsPresent::ContentTarget > targets = \r
37         GetContentTargets( document, filepath.parent_path() );\r
38 \r
39     fs::path current_xhtml_path;\r
40     boost::unordered_set< std::string > document_ids;\r
41 \r
42     foreach( const ContentTargetsPresent::ContentTarget &target, targets )\r
43     {\r
44         // They're sorted by content file path, so until\r
45         // the path changes, they all refer to the same file\r
46         if ( target.content_file != current_xhtml_path )\r
47         {\r
48             if ( !fs::exists( target.content_file ) )\r
49             {\r
50                 results.push_back( \r
51                     Result( ERROR_NCX_CONTENT_FILE_DOES_NOT_EXIST, target.content_node )\r
52                     .AddMessageArgument( target.raw_src_path )\r
53                     );\r
54 \r
55                 continue;\r
56             }\r
57 \r
58             current_xhtml_path = target.content_file;\r
59             document_ids       = GetAllIdsFromDocument( current_xhtml_path );                        \r
60         }\r
61 \r
62         if ( !target.fragment.empty() && !document_ids.count( target.fragment ) )\r
63         {\r
64             results.push_back( \r
65                 Result( ERROR_NCX_CONTENT_FRAGMENT_DOES_NOT_EXIST, target.content_node )\r
66                 .AddMessageArgument( target.raw_src_path )\r
67                 );\r
68         }\r
69     }\r
70 \r
71     return results;\r
72 }\r
73 \r
74 std::vector< ContentTargetsPresent::ContentTarget > ContentTargetsPresent::GetContentTargets( \r
75     const xc::DOMDocument &document, \r
76     const fs::path &folderpath )\r
77 {\r
78     std::vector< xc::DOMAttr* > srcs = xe::GetAllAttributesFromElements( \r
79         QName( "content", NCX_XML_NAMESPACE ),\r
80         QName( "src", "" ),\r
81         document );\r
82 \r
83     std::vector< ContentTargetsPresent::ContentTarget > targets;\r
84 \r
85     foreach( xc::DOMAttr* src, srcs )\r
86     {\r
87         ContentTargetsPresent::ContentTarget target;\r
88         \r
89         target.raw_src_path     = fromX( src->getValue() );\r
90         std::string decoded_url = Util::UrlDecode( target.raw_src_path );\r
91 \r
92         fs::path resource_path = \r
93             Util::Utf8PathToBoostPath(\r
94                 Util::UrlWithoutFragment( decoded_url ) ); \r
95 \r
96         target.content_file = Util::NormalizePath( folderpath / resource_path );        \r
97         target.fragment     = Util::GetUrlFragment( decoded_url );\r
98         target.content_node = xe::GetNodeLocationInfo( *src );\r
99 \r
100         targets.push_back( target );\r
101     }\r
102 \r
103     std::sort( targets.begin(), targets.end() );\r
104 \r
105     return targets;\r
106 }\r
107 \r
108 \r
109 boost::unordered_set< std::string > ContentTargetsPresent::GetAllIdsFromDocument( \r
110     const fs::path &filepath )\r
111 {\r
112     boost::shared_ptr< xc::DOMDocument > document;\r
113 \r
114     try\r
115     {\r
116         document = Util::LoadXhtmlDocument( filepath );\r
117     }\r
118 \r
119     catch ( std::exception& )\r
120     {\r
121         // If the file doesn't exist or some other\r
122         // snafu, then there are obviously no ids.\r
123         return boost::unordered_set< std::string > ();\r
124     }\r
125 \r
126     std::vector< xc::DOMAttr* > ids = xe::GetAllAttributesFromElements( \r
127         QName( "*", "*" ),\r
128         QName( "id", "*" ),\r
129         *document );\r
130 \r
131     boost::unordered_set< std::string > id_values;\r
132 \r
133     foreach( xc::DOMAttr* id, ids )\r
134     {        \r
135         std::string id_value = fromX( id->getValue() );\r
136 \r
137         id_values.insert( id_value );\r
138     }\r
139 \r
140     return id_values;\r
141 }\r
142 \r
143 } // namespace FlightCrew\r
144 \r