Loading plugins/content/content.cpp +28 −11 Changes for plugins/content/content.cpp: 28 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -72,6 +72,16 @@ namespace blogi { ~Content(){ }; // Strict YYYY-MM-DD check; only dates passing this go into SQL unescaped. static bool isValidDate(const std::string &date) { int y = 0; unsigned m = 0, d = 0; char tail = 0; return date.size() == 10 && std::isdigit(static_cast<unsigned char>(date[0])) && std::sscanf(date.c_str(), "%4d-%2u-%2u%c", &y, &m, &d, &tail) == 3 && std::chrono::year_month_day{std::chrono::year{y}, std::chrono::month{m}, std::chrono::day{d}}.ok(); } static std::string makeSlug(const char *title) { std::string slug; for (const char *p = title; *p; ++p) { Loading Loading @@ -1231,6 +1241,7 @@ namespace blogi { std::string text; std::string tags; std::string descrition; std::string created; if (!curform.getBoundary().empty()) { for (const auto &curformdat : curform.multipartData()) { Loading @@ -1253,6 +1264,14 @@ namespace blogi { else if (field == "blog_content") { text.append(curformdat.value.data(), curformdat.value.size()); } else if (field == "blog_created") { created.append(curformdat.value.data(), curformdat.value.size()); } } if (!created.empty() && !isValidDate(created)) { excep[libhttppp::HTTPException::Error] << tr(_lang,"Invalid publish date (expected YYYY-MM-DD)."); throw excep; } if (!text.empty() && !title.empty() && !descrition.empty()) { Loading @@ -1262,7 +1281,11 @@ namespace blogi { dbpp::SQL::escaped(sbuf,title.c_str()) << "',slug='" << dbpp::SQL::escaped(sbuf,slug.c_str()) << "',descrition='" << dbpp::SQL::escaped(sbuf,descrition.c_str()) << "',text='" << dbpp::SQL::escaped(sbuf,text.c_str()) << "' where id='" << cid << "';"; dbpp::SQL::escaped(sbuf,text.c_str()) << "'"; // Empty date field keeps the original publish date. if (!created.empty()) sqltext << ",created='" << created.c_str() << "'"; sqltext << " where id='" << cid << "';"; dbpp::DBResult textres; Loading Loading @@ -1328,7 +1351,7 @@ namespace blogi { } } sql = "SELECT title,descrition,text,tags.name FROM content "; sql = "SELECT title,descrition,text,tags.name,content.created FROM content "; sql << "LEFT JOIN tags_content ON tags_content.content_id = content.id " << "LEFT JOIN tags ON tags.id = tags_content.tag_id where content.id = '" << cid << "'"; Loading @@ -1353,6 +1376,8 @@ namespace blogi { condat << " "; } condat << "\" ><br>" << "<span>"+tr(_lang,"Publish date")+":</span><input name=\"blog_created\" type=\"date\" value=\"" << res[0][4].substr(0, 10) << "\" ><br>" << "<span>"+tr(_lang,"Text:")+"</span><textarea name=\"blog_content\" type=\"text\" style=\"width: 100%; height:480px;\" >" << res[0][2] << "</textarea>" << "<input type=\"submit\" value=\""+tr(_lang,"Post blog entry")+"\">" << "</form>" Loading Loading @@ -2212,19 +2237,11 @@ std::cerr << "DEBUG: authid=" << authid << " currentAuthor=" << currentAuthor << return; } // Only a strict, valid YYYY-MM-DD goes into SQL unescaped below. if (!publishDate.empty()) { int y = 0; unsigned m = 0, d = 0; char tail = 0; bool valid = publishDate.size() == 10 && std::sscanf(publishDate.c_str(), "%4d-%2u-%2u%c", &y, &m, &d, &tail) == 3 && std::chrono::year_month_day{std::chrono::year{y}, std::chrono::month{m}, std::chrono::day{d}}.ok(); if (!valid) { if (!publishDate.empty() && !isValidDate(publishDate)) { json_object_object_add(response, "status", json_object_new_string("error")); json_object_object_add(response, "message", json_object_new_string(tr(_lang,"Invalid publish date (expected YYYY-MM-DD).").c_str())); return; } } try { std::string time_str = publishDate; Loading Loading
plugins/content/content.cpp +28 −11 Changes for plugins/content/content.cpp: 28 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -72,6 +72,16 @@ namespace blogi { ~Content(){ }; // Strict YYYY-MM-DD check; only dates passing this go into SQL unescaped. static bool isValidDate(const std::string &date) { int y = 0; unsigned m = 0, d = 0; char tail = 0; return date.size() == 10 && std::isdigit(static_cast<unsigned char>(date[0])) && std::sscanf(date.c_str(), "%4d-%2u-%2u%c", &y, &m, &d, &tail) == 3 && std::chrono::year_month_day{std::chrono::year{y}, std::chrono::month{m}, std::chrono::day{d}}.ok(); } static std::string makeSlug(const char *title) { std::string slug; for (const char *p = title; *p; ++p) { Loading Loading @@ -1231,6 +1241,7 @@ namespace blogi { std::string text; std::string tags; std::string descrition; std::string created; if (!curform.getBoundary().empty()) { for (const auto &curformdat : curform.multipartData()) { Loading @@ -1253,6 +1264,14 @@ namespace blogi { else if (field == "blog_content") { text.append(curformdat.value.data(), curformdat.value.size()); } else if (field == "blog_created") { created.append(curformdat.value.data(), curformdat.value.size()); } } if (!created.empty() && !isValidDate(created)) { excep[libhttppp::HTTPException::Error] << tr(_lang,"Invalid publish date (expected YYYY-MM-DD)."); throw excep; } if (!text.empty() && !title.empty() && !descrition.empty()) { Loading @@ -1262,7 +1281,11 @@ namespace blogi { dbpp::SQL::escaped(sbuf,title.c_str()) << "',slug='" << dbpp::SQL::escaped(sbuf,slug.c_str()) << "',descrition='" << dbpp::SQL::escaped(sbuf,descrition.c_str()) << "',text='" << dbpp::SQL::escaped(sbuf,text.c_str()) << "' where id='" << cid << "';"; dbpp::SQL::escaped(sbuf,text.c_str()) << "'"; // Empty date field keeps the original publish date. if (!created.empty()) sqltext << ",created='" << created.c_str() << "'"; sqltext << " where id='" << cid << "';"; dbpp::DBResult textres; Loading Loading @@ -1328,7 +1351,7 @@ namespace blogi { } } sql = "SELECT title,descrition,text,tags.name FROM content "; sql = "SELECT title,descrition,text,tags.name,content.created FROM content "; sql << "LEFT JOIN tags_content ON tags_content.content_id = content.id " << "LEFT JOIN tags ON tags.id = tags_content.tag_id where content.id = '" << cid << "'"; Loading @@ -1353,6 +1376,8 @@ namespace blogi { condat << " "; } condat << "\" ><br>" << "<span>"+tr(_lang,"Publish date")+":</span><input name=\"blog_created\" type=\"date\" value=\"" << res[0][4].substr(0, 10) << "\" ><br>" << "<span>"+tr(_lang,"Text:")+"</span><textarea name=\"blog_content\" type=\"text\" style=\"width: 100%; height:480px;\" >" << res[0][2] << "</textarea>" << "<input type=\"submit\" value=\""+tr(_lang,"Post blog entry")+"\">" << "</form>" Loading Loading @@ -2212,19 +2237,11 @@ std::cerr << "DEBUG: authid=" << authid << " currentAuthor=" << currentAuthor << return; } // Only a strict, valid YYYY-MM-DD goes into SQL unescaped below. if (!publishDate.empty()) { int y = 0; unsigned m = 0, d = 0; char tail = 0; bool valid = publishDate.size() == 10 && std::sscanf(publishDate.c_str(), "%4d-%2u-%2u%c", &y, &m, &d, &tail) == 3 && std::chrono::year_month_day{std::chrono::year{y}, std::chrono::month{m}, std::chrono::day{d}}.ok(); if (!valid) { if (!publishDate.empty() && !isValidDate(publishDate)) { json_object_object_add(response, "status", json_object_new_string("error")); json_object_object_add(response, "message", json_object_new_string(tr(_lang,"Invalid publish date (expected YYYY-MM-DD).").c_str())); return; } } try { std::string time_str = publishDate; Loading