// // aegis - project change supervisor // Copyright (C) 2005-2008, 2010, 2012, 2014 Peter Miller // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or (at // your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // #include #include #include #include #include #include #include #include #include #include #include validation_files_copyright::~validation_files_copyright() { } static nstring calc_year(void) { time_t when = now(); struct tm *tmp = localtime(&when); char buffer[10]; strftime(buffer, sizeof(buffer), "%Y", tmp); return nstring(buffer); } validation_files_copyright::validation_files_copyright() : year(calc_year()) { } validation::pointer validation_files_copyright::create(void) { return pointer(new validation_files_copyright()); } bool validation_files_copyright::check_branches(void) const { return false; } bool validation_files_copyright::check_downloaded(void) const { return false; } bool validation_files_copyright::check_foreign_copyright(void) const { return false; } bool validation_files_copyright::check_binaries(void) const { return false; } static const char * strstr_end(const char *haystack, const char *needle) { const char *p = strstr(haystack, needle); if (p) p += strlen(needle); return p; } enum encoding_t { encoding_ascii7, encoding_html, encoding_utf8, }; static encoding_t encoding = encoding_ascii7; struct table_t { const char *pattern; encoding_t encoding; }; static const table_t table[] = { { "(C)", encoding_ascii7 }, { "(c)", encoding_ascii7 }, { "©", encoding_html }, { "©", encoding_html }, { "©", encoding_html }, { "\xC2\xA9", encoding_utf8 }, }; static const char * look_for_symbol(const char *text) { for (const table_t *tp = table; tp < ENDOF(table); ++tp) { const char *result = strstr_end(text, tp->pattern); if (result) { encoding = tp->encoding; return result; } } return NULL; } static const char * circle_c_from_encoding(encoding_t x) { for (const table_t *tp = table; tp < ENDOF(table); ++tp) { if (tp->encoding == x) return tp->pattern; } return "(C)"; } const char * validation_files_copyright::look_for_year(const char *text) const { const char *p = strstr_end(text, year.c_str()); if (!p) p = strstr_end(text, "${date +%Y}"); return p; } bool validation_files_copyright::check(change::pointer cp, fstate_src_ty *src) { // // We can only know the copyright owner once we know the change set, // because it can be changed by a change set. // if (who.empty()) { who = nstring(cp->pconf_copyright_owner_get()); } nstring path(cp->file_path(src)); assert(!path.empty()); if (path.empty()) return true; os_become_orig(); bool result = true; bool copyright_seen = false; bool public_domain_seen = false; input::pointer ip = input_file::open(path); nstring_accumulator sa; for (;;) { sa.clear(); for (;;) { int c = ip->getch(); if (c < 0) { if (sa.empty()) goto end_of_file; break; } if (c == 0) { // // Binary files are exempt from the copyright check. // Image formats usually have a place to put a copyright // notice, but there is no good way to check this. // ip.reset(); os_become_undo(); return true; } if (c == '\n') break; sa.push_back((unsigned char)c); } nstring line = sa.mkstr(); // // A properly conforming copyright notice: // As established by case law, the order should be // Copyright + (C) + year + who; // However, we accept them in any order, including "Copyright" // being missing. // #if 0 const char *cr_ep = strstr_end(line.downcase().c_str(), "copyright"); #endif const char *copy_ep = look_for_symbol(line.c_str()); const char *year_ep = look_for_year(line.c_str()); const char *who_ep = strstr_end(line.c_str(), who.c_str()); const char *pubdom_ep = strstr_end(line.c_str(), "Public Domain"); if (copy_ep && year_ep && who_ep) { // // // if (cr_ep && copy_ep && year_ep && who_ep // && cr_ep < copy_ep // && copy_ep < year_ep // && year_ep < who_ep) // // copyright_seen = true; } if (pubdom_ep && who_ep) { public_domain_seen = true; } } end_of_file: ip.reset(); os_become_undo(); if (!copyright_seen && !public_domain_seen) { // A properly conforming copyright notice, // As established by case law, the order shall be: // Copyright + (C) + year + who; nstring suggest = "Copyright "; suggest += circle_c_from_encoding(encoding); suggest += " "; suggest += year; suggest += " "; suggest += who; // we have to do this after vopy_ep is obtained, because it // determines the circle_c form to be used. sub_context_ty sc; sc.var_set_string("File_Name", src->file_name); sc.var_set_string("Suggest", suggest); sc.var_optional("Suggest"); change_error(cp, &sc, i18n("$filename: no current copyright notice")); result = false; } return result; } // vim: set ts=8 sw=4 et :