#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 #include #include static void cgit_print_file_links( struct strbuf *sb, const char *relative_path, const char *revision, int top ) { const char *query_string = NULL; const char *place = NULL; if( !sb || !relative_path ) return; if( top ) place = "top"; else place = "bottom"; strbuf_addf( sb, "
\n", place ); strbuf_addf( sb, "
\n" ); query_string = ctx_remove_query_param( ctx.env.query_string, "rev" ); query_string = ctx_remove_query_param( query_string, "op" ); if( query_string && *query_string ) { strbuf_addf( sb, " \n", ctx.repo.name, relative_path, revision, query_string ); strbuf_addf( sb, " \n", ctx.repo.name, relative_path, revision, query_string ); strbuf_addf( sb, " \n", ctx.repo.name, relative_path, revision, query_string ); } else { strbuf_addf( sb, " \n", ctx.repo.name, relative_path, revision ); strbuf_addf( sb, " \n", ctx.repo.name, relative_path, revision ); strbuf_addf( sb, " \n", ctx.repo.name, relative_path, revision ); } strbuf_addf( sb, "
\n" ); strbuf_addf( sb, "
\n" ); } static void process_markdown_output( const MD_CHAR *text, MD_SIZE size, void *sb ) { strbuf_add( (struct strbuf *)sb, (const void *)text, (size_t)size ); } static int cgit_write_markdown_content( struct strbuf *sb, const struct strbuf *input ) { unsigned parser_flags = MD_DIALECT_GITHUB; /* | MD_DIALECT_COMMONMARK */ unsigned renderer_flags = MD_FLAG_WIKILINKS; /* | MD_HTML_FLAG_DEBUG */ /********************************* md_html() returns 0 on success: */ return md_html( input->buf, input->len, process_markdown_output, (void *)sb, parser_flags, renderer_flags ); } static void cgit_print_file( struct strbuf *sb, const char *relative_path, const char *revision ) { struct cgit_info info; if( !sb || !relative_path ) return; if( revision && strcmp( revision, (const char *)&ctx.repo.relative_info.revision[0] ) ) { cgit_rpath_info( &info, relative_path, revision ); if( info.kind != GIT_OBJECT_BLOB ) { strbuf_addf( sb, "

Requested resource cannot be shown

\n" ); strbuf_addf( sb, "

File with specified revision '%s' cannot be shown.

\n", revision ); return; } } else { memcpy( (void *)&info, (void *)&ctx.repo.relative_info, sizeof( struct cgit_info ) ); } cgit_print_file_links( sb, relative_path, (const char *)&info.revision[0], 1 ); if( info.lang ) { if( !strcmp( info.lang, "Markdown" ) ) strbuf_addstr( sb, "
" ); else strbuf_addf( sb, "
", info.lang );
  }
  else
    strbuf_addstr( sb, "
" );

  if( info.kind == GIT_OBJECT_BLOB )
  {
    git_repository *repo = NULL;
    git_blob       *blob = NULL;
    git_oid         oid;
    /* git_off_t       rawsize = 0; */
    const char     *rawcontent = NULL;

    if( git_oid_fromstr( &oid, (const char *)&info.oid[0] ) < 0 )
    {
      if( info.lang && !strcmp( info.lang, "Markdown" ) )
        strbuf_addstr( sb, "\n
\n" ); else strbuf_addstr( sb, "\n\n" ); cgit_print_file_links( sb, relative_path, (const char *)&info.revision[0], 0 ); return; } if( !(repo = cgit_open_repository()) ) { if( info.lang && !strcmp( info.lang, "Markdown" ) ) strbuf_addstr( sb, "\n \n" ); else strbuf_addstr( sb, "\n\n" ); cgit_print_file_links( sb, relative_path, (const char *)&info.revision[0], 0 ); return; } if( git_blob_lookup( &blob, repo, &oid ) < 0 ) { close_repository( repo ); if( info.lang && !strcmp( info.lang, "Markdown" ) ) strbuf_addstr( sb, "\n \n" ); else strbuf_addstr( sb, "\n\n" ); cgit_print_file_links( sb, relative_path, (const char *)&info.revision[0], 0 ); return; } /* rawsize = git_blob_rawsize( blob ); */ rawcontent = (const char *)git_blob_rawcontent( blob ); if( !git_blob_is_binary( blob ) && rawcontent && *rawcontent ) { struct strbuf buf = STRBUF_INIT; if( info.lang && !strcmp( info.lang, "Markdown" ) ) { strbuf_addstr( &buf, (const char *)rawcontent ); (void)cgit_write_markdown_content( sb, (const struct strbuf *)&buf ); strbuf_release( &buf ); } else { strbuf_addstr_xml_quoted( &buf, (const char *)rawcontent ); strbuf_addbuf( sb, (const struct strbuf *)&buf ); strbuf_release( &buf ); } } else { git_blob_free( blob ); close_repository( repo ); if( info.lang && !strcmp( info.lang, "Markdown" ) ) strbuf_addstr( sb, "\n \n" ); else strbuf_addstr( sb, "\n\n" ); cgit_print_file_links( sb, relative_path, (const char *)&info.revision[0], 0 ); return; } git_blob_free( blob ); close_repository( repo ); } if( info.lang && !strcmp( info.lang, "Markdown" ) ) strbuf_addstr( sb, "\n \n" ); else strbuf_addstr( sb, "\n\n" ); cgit_print_file_links( sb, relative_path, (const char *)&info.revision[0], 0 ); return; } static void cgit_print_image_file( struct strbuf *sb, const char *relative_path, const char *revision ) { struct cgit_info info; if( !sb || !relative_path ) return; if( revision && strcmp( revision, (const char *)&ctx.repo.relative_info.revision[0] ) ) { cgit_rpath_info( &info, relative_path, revision ); if( info.kind != GIT_OBJECT_BLOB ) { strbuf_addf( sb, "

Invalid Revision

\n" ); strbuf_addf( sb, "

File with specified revision '%s' cannot be shown.

\n", revision ); return; } } else { memcpy( (void *)&info, (void *)&ctx.repo.relative_info, sizeof( struct cgit_info ) ); } if( info.kind == GIT_OBJECT_BLOB ) { git_repository *repo = NULL; git_blob *blob = NULL; git_oid oid; git_off_t rawsize = 0; const char *rawcontent = NULL; if( git_oid_fromstr( &oid, (const char *)&info.oid[0] ) < 0 ) return; if( !(repo = cgit_open_repository()) ) return; if( git_blob_lookup( &blob, repo, &oid ) < 0 ) { close_repository( repo ); return; } rawsize = git_blob_rawsize( blob ); rawcontent = (const char *)git_blob_rawcontent( blob ); if( rawcontent && *rawcontent ) { struct strbuf buf = STRBUF_INIT; strbuf_add( &buf, (const void *)rawcontent, (size_t)rawsize ); git_blob_free( blob ); close_repository( repo ); /**************************************************** This call should terminate the program on success: */ cgit_print_raw_file( &buf, info.mime ); strbuf_release( &buf ); } else { git_blob_free( blob ); close_repository( repo ); return; } git_blob_free( blob ); close_repository( repo ); } return; } void cgit_print_file_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.relative_info.kind == GIT_OBJECT_BLOB ) { if( !strncmp( ctx.repo.relative_info.mime, "text/", 5 ) ) { if( ctx.repo.name ) { cgit_print_file( &buf, ctx.repo.relative_path, (!strcmp( ctx.query.rev, "0" )) ? (const char *)&ctx.repo.relative_info.revision[0] : ctx.query.rev ); } else { strbuf_addf( &buf, "

Requested resource cannot be shown

\n" ); strbuf_addf( &buf, "

Repository '%s' not found.

\n", ctx.repo.name ); } } else if( !strncmp( ctx.repo.relative_info.mime, "image/", 6 ) ) { /**************************************************** This call should terminate the program on success: */ cgit_print_image_file( &buf, ctx.repo.relative_path, (!strcmp( ctx.query.rev, "0" )) ? (const char *)&ctx.repo.relative_info.revision[0] : ctx.query.rev ); strbuf_addf( &buf, "

Requested file cannot be shown

\n" ); strbuf_addf( &buf, "

Files with mime type such as '%s' cannot be present.

\n", ctx.repo.relative_info.mime ); } else { strbuf_addf( &buf, "

Requested file cannot be shown

\n" ); strbuf_addf( &buf, "

Files with mime type such as '%s' cannot be present.

\n", ctx.repo.relative_info.mime ); } } else { strbuf_addf( &buf, "

Requested resource cannot be shown

\n" ); strbuf_addf( &buf, "

This page assume plain text files to be present.

\n" ); } 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; cgit_print_http_headers(); strbuf_write( &buf, STDOUT_FILENO ); strbuf_release( &buf ); }