From bfc1508d26c89c9a36d2d9a827fe2c4ed128884d Mon Sep 17 00:00:00 2001 From: kx Date: Fri, 24 Mar 2023 03:55:33 +0300 Subject: Version 0.1.4 --- csvncgi/ui-log.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 csvncgi/ui-log.c (limited to 'csvncgi/ui-log.c') diff --git a/csvncgi/ui-log.c b/csvncgi/ui-log.c new file mode 100644 index 0000000..d0c17b6 --- /dev/null +++ b/csvncgi/ui-log.c @@ -0,0 +1,343 @@ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#ifdef HAVE_INTTYPES_H +#include +#else +#include +#endif +#include /* offsetof(3) */ +#include +#include /* chmod(2) */ +#include +#include +#include +#include +#include /* strdup(3) */ +#include /* basename(3) */ +#include /* tolower(3) */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + + +static void xml_csvn_log( struct strbuf *sb, const struct strbuf *buf, const char *relative_path ) +{ + xmlDocPtr doc = NULL; + xmlNode *root = NULL; + char *path = NULL; + + int count = 0, printed = 0, reminder = 0, page_size = 200; + + if( !sb || !sb->len || !buf || !buf->buf ) return; + if( relative_path && *relative_path ) + { + path = (char *)xmalloc( strlen( relative_path ) + 2 ); + path[0] = '/'; + sprintf( (char *)&path[1], relative_path ); + } + else + { + path = (char *)xmalloc( 1 ); + path[0] = '\0'; + } + + page_size = atoi( ctx.vars.page_size ); + + LIBXML_TEST_VERSION + + doc = xmlReadMemory( buf->buf, buf->len, "log.xml", NULL, 0 ); + if( !doc ) + { + html_fatal( "cannot parse svn log.xml" ); + return; + } + + root = xmlDocGetRootElement( doc ); + if( !root ) + { + free( path ); + xmlFreeDoc( doc ); + xmlCleanupParser(); + return; + } + + if( !strcmp( "log", (char *)root->name ) ) + { + xmlNode *node = NULL; + + strbuf_addstr( sb, "\n" ); + strbuf_addf( sb, "
\n" ); + strbuf_addf( sb, "
\n" ); + strbuf_addf( sb, "
Date
\n" ); + strbuf_addf( sb, "
Commit Message
\n" ); + strbuf_addf( sb, "
Rev
\n" ); + strbuf_addf( sb, "
Author
\n" ); + strbuf_addf( sb, "
\n" ); + strbuf_addf( sb, "
\n\n" ); + + strbuf_addf( sb, "
\n\n" ); + + /************************** + Print directories first: + */ + for( node = root->children; node; node = node->next ) + { + if( node->type == XML_ELEMENT_NODE && !strcmp( "logentry", (char *)node->name ) ) + { + xmlNode *param = NULL; + xmlChar *date = NULL, *cmsg = NULL, *revision = NULL, *author = NULL; + + revision = xmlGetProp( node, (const unsigned char *)"revision" ); + + for( param = node->children; param; param= param->next ) + { + if( param->type == XML_ELEMENT_NODE && !strcmp( "date", (char *)param->name ) ) + { + date = xmlNodeGetContent( param ); + } + if( param->type == XML_ELEMENT_NODE && !strcmp( "msg", (char *)param->name ) ) + { + cmsg = xmlNodeGetContent( param ); + } + if( param->type == XML_ELEMENT_NODE && !strcmp( "author", (char *)param->name ) ) + { + author = xmlNodeGetContent( param ); + } + + } /* End for entry parameters */ + + if( date && cmsg && revision && author ) + { + struct tm tm; + time_t time = -1; + const char *query_string = ctx_remove_query_param( ctx.env.query_string, "rev" ); + + query_string = ctx_remove_query_param( query_string, "op" ); + + time = parse_date( &tm, (const char *)date ); + + ++count; + if( count > ctx.query.ofs && printed < page_size ) + { + + strbuf_addf( sb, "
\n" ); + if( time != -1 ) + { + strbuf_addf( sb, "
" ); + csvn_print_age( sb, time, 0, 0 ); + strbuf_addf( sb, "
\n" ); + } + else + { + strbuf_addf( sb, "
unknown
\n" ); + } + strbuf_addf( sb, "
%s
\n", (char *)cmsg ); + if( query_string && *query_string ) + { + strbuf_addf( sb, " \n", ctx.repo.name, path, (char *)revision, query_string, (char *)revision ); + } + else + { + strbuf_addf( sb, " \n", ctx.repo.name, path, (char *)revision, (char *)revision ); + } + strbuf_addf( sb, "
%s
\n", (char *)author ); + strbuf_addf( sb, "
\n\n" ); + + ++printed; + } + + xmlFree( date ); + xmlFree( cmsg ); + xmlFree( revision ); + xmlFree( author ); + } + else + { + if( date ) xmlFree( date ); + if( cmsg ) xmlFree( cmsg ); + if( revision ) xmlFree( revision ); + if( author ) xmlFree( author ); + } + } + } + + strbuf_addf( sb, "
\n\n" ); + + /******************************** + Print log direction: + */ + reminder = count - ctx.query.ofs - printed; + if( page_size < count ) + { + int prev, next; + + strbuf_addf( sb, "
\n" ); + strbuf_addf( sb, "
\n" ); + strbuf_addf( sb, "
\n" ); + strbuf_addf( sb, "
\n" ); + + if( ctx.query.ofs ) + { + prev = ctx.query.ofs - page_size; + if( prev < 0 ) prev = 0; + + if( ctx.env.query_string && *ctx.env.query_string ) + strbuf_addf( sb, " ≪  Prev\n", ctx.repo.name, path, prev, ctx.env.query_string ); + else + strbuf_addf( sb, " ≪  Prev\n", ctx.repo.name, path, prev ); + } + + strbuf_addf( sb, "
\n" ); + strbuf_addf( sb, "
\n" ); + strbuf_addf( sb, "
\n" ); + strbuf_addf( sb, "
\n" ); + + if( reminder ) + { + next = ctx.query.ofs + page_size; + + if( ctx.env.query_string && *ctx.env.query_string ) + strbuf_addf( sb, " Next  ≫\n", ctx.repo.name, path, next, ctx.env.query_string ); + else + strbuf_addf( sb, " Next  ≫\n", ctx.repo.name, path, next ); + } + + strbuf_addf( sb, "
\n" ); + strbuf_addf( sb, "
\n" ); + strbuf_addf( sb, "
\n" ); + strbuf_addf( sb, "
\n" ); + } + /* + End of printing log direction. + ********************************/ + + } + + free( path ); + xmlFreeDoc(doc); + xmlCleanupParser(); +} + +static void csvn_print_log( struct strbuf *sb, const char *relative_path, int revision ) +{ + const char *co_prefix = ctx.repo.checkout_ro_prefix; + const char *repo_path = ctx.repo.name; + char *path = NULL; + + if( !sb ) return; + + if( relative_path && *relative_path ) + { + path = (char *)xmalloc( strlen( relative_path ) + 2 ); + path[0] = '/'; + sprintf( (char *)&path[1], relative_path ); + } + else + { + path = (char *)xmalloc( 1 ); + path[0] = '\0'; + } + + if( co_prefix ) + { + char cmd[1024]; + struct strbuf buf = STRBUF_INIT; + pid_t p = (pid_t) -1; + int rc; + + if( revision ) + snprintf( (char *)&cmd[0], 1024, + "svn log --revision %d:0 --xml %s/%s%s 2>/dev/null", + revision, co_prefix, repo_path, path ); + else + snprintf( (char *)&cmd[0], 1024, + "svn log --xml %s/%s%s 2>/dev/null", + co_prefix, repo_path, path ); + p = sys_exec_command( &buf, cmd ); + rc = sys_wait_command( p, NULL ); + if( rc != 0 ) + { + strbuf_release( &buf ); + free( path ); + return; + } + + xml_csvn_log( sb, (const struct strbuf *)&buf, relative_path ); + + strbuf_release( &buf ); + } + + free( path ); + return; +} + + +void csvn_print_log_page( void ) +{ + FILE *fp; + struct strbuf buf = STRBUF_INIT; + + fp = xfopen( ctx.page.header, "r" ); + (void)strbuf_env_fread( &buf, fp ); + fclose( fp ); + + strbuf_addf( &buf, "
\n" ); + strbuf_addf( &buf, "
\n" ); + strbuf_addf( &buf, "
\n" ); + + if( ctx.repo.name ) + { + csvn_print_log( &buf, ctx.repo.relative_path, ctx.query.rev ); + } + else + { + strbuf_addf( &buf, "

Requested resource cannot be shown

\n" ); + strbuf_addf( &buf, "

Repository '%s' not found.

\n", ctx.repo.name ); + } + + strbuf_addf( &buf, "
\n" ); + strbuf_addf( &buf, "
\n" ); + strbuf_addf( &buf, "
\n" ); + + fp = xfopen( ctx.page.footer, "r" ); + (void)strbuf_env_fread( &buf, fp ); + fclose( fp ); + + ctx.page.size = buf.len; + csvn_print_http_headers(); + strbuf_write( &buf, STDOUT_FILENO ); + strbuf_release( &buf ); +} -- cgit v1.2.3