Disable stack execution on plugins
[claws.git] / src / plugins / litehtml_viewer / litehtml / stylesheet.cpp
blob8c4b784311349aefd777f1c32ba100050ca76ded
1 #include "html.h"
2 #include "stylesheet.h"
3 #include <algorithm>
4 #include "document.h"
7 void litehtml::css::parse_stylesheet(const char* str, const char* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media)
9 string text = str;
11 // remove comments
12 string::size_type c_start = text.find("/*");
13 while(c_start != string::npos)
15 string::size_type c_end = text.find("*/", c_start + 2);
16 if(c_end == string::npos)
18 text.erase(c_start);
19 break;
21 text.erase(c_start, c_end - c_start + 2);
22 c_start = text.find("/*");
25 string::size_type pos = text.find_first_not_of(" \n\r\t");
26 while(pos != string::npos)
28 while(pos != string::npos && text[pos] == '@')
30 string::size_type sPos = pos;
31 pos = text.find_first_of("{;", pos);
32 if(pos != string::npos && text[pos] == '{')
34 pos = find_close_bracket(text, pos, '{', '}');
36 if(pos != string::npos)
38 parse_atrule(text.substr(sPos, pos - sPos + 1), baseurl, doc, media);
39 } else
41 parse_atrule(text.substr(sPos), baseurl, doc, media);
44 if(pos != string::npos)
46 pos = text.find_first_not_of(" \n\r\t", pos + 1);
50 if(pos == string::npos)
52 break;
55 string::size_type style_start = text.find('{', pos);
56 string::size_type style_end = text.find('}', pos);
57 if(style_start != string::npos && style_end != string::npos)
59 auto str_style = text.substr(style_start + 1, style_end - style_start - 1);
60 style::ptr style = std::make_shared<litehtml::style>();
61 style->add(str_style, baseurl ? baseurl : "", doc->container());
63 parse_selectors(text.substr(pos, style_start - pos), style, media);
65 if(media && doc)
67 doc->add_media_list(media);
70 pos = style_end + 1;
71 } else
73 pos = string::npos;
76 if(pos != string::npos)
78 pos = text.find_first_not_of(" \n\r\t", pos);
83 void litehtml::css::parse_css_url( const string& str, string& url )
85 url = "";
86 size_t pos1 = str.find('(');
87 size_t pos2 = str.find(')');
88 if(pos1 != string::npos && pos2 != string::npos)
90 url = str.substr(pos1 + 1, pos2 - pos1 - 1);
91 if(url.length())
93 if(url[0] == '\'' || url[0] == '"')
95 url.erase(0, 1);
98 if(url.length())
100 if(url[url.length() - 1] == '\'' || url[url.length() - 1] == '"')
102 url.erase(url.length() - 1, 1);
108 bool litehtml::css::parse_selectors( const string& txt, const style::ptr& styles, const media_query_list::ptr& media )
110 string selector = txt;
111 trim(selector);
112 string_vector tokens;
113 split_string(selector, tokens, ",");
115 bool added_something = false;
117 for(auto & token : tokens)
119 css_selector::ptr new_selector = std::make_shared<css_selector>(media);
120 new_selector->m_style = styles;
121 trim(token);
122 if(new_selector->parse(token))
124 new_selector->calc_specificity();
125 add_selector(new_selector);
126 added_something = true;
130 return added_something;
133 void litehtml::css::sort_selectors()
135 std::sort(m_selectors.begin(), m_selectors.end(),
136 [](const css_selector::ptr& v1, const css_selector::ptr& v2)
138 return (*v1) < (*v2);
143 void litehtml::css::parse_atrule(const string& text, const char* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media)
145 if(text.substr(0, 7) == "@import")
147 int sPos = 7;
148 string iStr;
149 iStr = text.substr(sPos);
150 if(iStr[iStr.length() - 1] == ';')
152 iStr.erase(iStr.length() - 1);
154 trim(iStr);
155 string_vector tokens;
156 split_string(iStr, tokens, " ", "", "(\"");
157 if(!tokens.empty())
159 string url;
160 parse_css_url(tokens.front(), url);
161 if(url.empty())
163 url = tokens.front();
165 tokens.erase(tokens.begin());
166 if(doc)
168 document_container* doc_cont = doc->container();
169 if(doc_cont)
171 string css_text;
172 string css_baseurl;
173 if(baseurl)
175 css_baseurl = baseurl;
177 doc_cont->import_css(css_text, url, css_baseurl);
178 if(!css_text.empty())
180 media_query_list::ptr new_media = media;
181 if(!tokens.empty())
183 string media_str;
184 for(auto iter = tokens.begin(); iter != tokens.end(); iter++)
186 if(iter != tokens.begin())
188 media_str += " ";
190 media_str += (*iter);
192 new_media = media_query_list::create_from_string(media_str, doc);
193 if(!new_media)
195 new_media = media;
198 parse_stylesheet(css_text.c_str(), css_baseurl.c_str(), doc, new_media);
203 } else if(text.substr(0, 6) == "@media")
205 string::size_type b1 = text.find_first_of('{');
206 string::size_type b2 = text.find_last_of('}');
207 if(b1 != string::npos)
209 string media_type = text.substr(6, b1 - 6);
210 trim(media_type);
211 media_query_list::ptr new_media = media_query_list::create_from_string(media_type, doc);
213 string media_style;
214 if(b2 != string::npos)
216 media_style = text.substr(b1 + 1, b2 - b1 - 1);
217 } else
219 media_style = text.substr(b1 + 1);
222 parse_stylesheet(media_style.c_str(), baseurl, doc, new_media);