From 9844f440f4373e93b8fea0a7cf54dcd0441f9069 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 20 May 2003 00:03:39 +0000 Subject: [PATCH] user-specified files in app versions svn path=/trunk/boinc/; revision=1219 --- api/graphics_data.C | 19 +++++++ api/graphics_data.h | 2 +- api/gutil.cpp | 22 ++++++++- api/gutil.h | 31 +++++++++++- checkin_notes | 60 +++++++++++++++++++++++ client/app.C | 5 +- client/client_state.C | 6 ++- client/client_types.C | 9 +++- client/cs_files.C | 2 +- client/cs_scheduler.C | 19 +++---- client/file_names.C | 32 +----------- client/pers_file_xfer.C | 31 +++++++----- client/pers_file_xfer.h | 4 +- doc/api.html | 98 ------------------------------------- doc/boinc_dev.html | 4 +- doc/client_app.html | 96 ++++++++++++++++++++++++++++++++++++ doc/client_app_graphic.html | 19 ++++++- doc/graphics.html | 23 --------- lib/parse.C | 15 ++++++ lib/parse.h | 1 + lib/util.C | 34 +++++++++++++ lib/util.h | 1 + sched/handle_request.C | 74 +++++++++++++++++++++++++++- sched/server_types.C | 20 ++++++++ sched/server_types.h | 8 +++ todo | 1 - 26 files changed, 441 insertions(+), 195 deletions(-) diff --git a/api/graphics_data.C b/api/graphics_data.C index 6f3548a82b..f1cfe2cbe0 100644 --- a/api/graphics_data.C +++ b/api/graphics_data.C @@ -1,3 +1,22 @@ +// The contents of this file are subject to the Mozilla Public License +// Version 1.0 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.mozilla.org/MPL/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +// The Original Code is the Berkeley Open Infrastructure for Network Computing. +// +// The Initial Developer of the Original Code is the SETI@home project. +// Portions created by the SETI@home project are Copyright (C) 2002 +// University of California at Berkeley. All Rights Reserved. +// +// Contributor(s): +// + #include "graphics_data.h" void GRAPHICS_BUFFER::clear() { diff --git a/api/graphics_data.h b/api/graphics_data.h index 573c3565ae..faee7c568d 100644 --- a/api/graphics_data.h +++ b/api/graphics_data.h @@ -17,7 +17,7 @@ // Contributor(s): // -// The class GRAPHICS_DOUBLE_BUFFER provides a handy mechanism +// The class GRAPHICS_DOUBLE_BUFFER provides a mechanism // for synchronizing the generation of graphics information // (done by the "science thread") // with the graphics rendering (done by the "GUI thread", diff --git a/api/gutil.cpp b/api/gutil.cpp index 59a4f445a8..483d766ae4 100755 --- a/api/gutil.cpp +++ b/api/gutil.cpp @@ -1,3 +1,22 @@ +// The contents of this file are subject to the Mozilla Public License +// Version 1.0 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.mozilla.org/MPL/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +// The Original Code is the Berkeley Open Infrastructure for Network Computing. +// +// The Initial Developer of the Original Code is the SETI@home project. +// Portions created by the SETI@home project are Copyright (C) 2002 +// University of California at Berkeley. All Rights Reserved. +// +// Contributor(s): +// + #include #include #include @@ -14,7 +33,7 @@ #endif #include "gutil.h" -GLfloat mat_diffuse[] = {0.7, 0.5, 1.0, 0.4}; +//GLfloat mat_diffuse[] = {0.7, 0.5, 1.0, 0.4}; GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0}; GLfloat mat_shininess[] = {40.0}; @@ -36,7 +55,6 @@ void mode_texture() { glLoadIdentity(); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); - //glTranslatef( 0.0f, 0.0f, -4.0f ); } void mode_unshaded() { diff --git a/api/gutil.h b/api/gutil.h index 52ce9862ae..cb30af5732 100755 --- a/api/gutil.h +++ b/api/gutil.h @@ -1,3 +1,26 @@ +// The contents of this file are subject to the Mozilla Public License +// Version 1.0 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.mozilla.org/MPL/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +// The Original Code is the Berkeley Open Infrastructure for Network Computing. +// +// The Initial Developer of the Original Code is the SETI@home project. +// Portions created by the SETI@home project are Copyright (C) 2002 +// University of California at Berkeley. All Rights Reserved. +// +// Contributor(s): +// + +// various utility classes for OpenGL programming, +// used in Astropulse and SETI@home +// See also graphics_data.C,h + struct COLOR { GLfloat r; GLfloat g; @@ -26,7 +49,8 @@ extern GLfloat text_width(char* text); extern void draw_text_panel( GLfloat* _pos, GLfloat* size, GLfloat margin, COLOR color, GLfloat char_height, GLfloat line_width, GLfloat line_spacing, - char* text); + char* text +); extern void mode_texture(); extern void mode_shaded(GLfloat*); @@ -59,7 +83,10 @@ public: void add_tick(float x, float yfrac); }; +// read a portable pixmap file +// extern int read_ppm(char* name, int& w, int& h, unsigned char** arrayp); extern void init_texture(char* filename); -extern void draw_texture(float* pos, float* size); \ No newline at end of file +extern void draw_texture(float* pos, float* size); + diff --git a/checkin_notes b/checkin_notes index a11fa4478e..d1ebae32aa 100755 --- a/checkin_notes +++ b/checkin_notes @@ -4212,3 +4212,63 @@ Eric May 16, 2003 net_xfer.C win/ wingui_mainwindow.cpp + +Erik May 19 2003 + - added support for user-selected files to be included + as part of an app_version. + If there is an element of the form + + X + Y + + in a user's project preferences, + then for every APP_VERSION that is sent to the user, + elements of the form + + X' + X + + ... and in the element + + X' + Y + + are added to the app version's XML description, + where X' is an escaped version of X. + This can be used (for example) to allow applications to + have user-specified images in their graphics + - Handle it correctly if the "insert" part of a file transfer fails + - The "main program" of an app version is the one labeled + (not necessarily the first one) + - Only files labeled are required to be signed + - added copyright notice to some files + - added sgets() for parsing a string that is made up of multiple lines + - write MD5 checksum elements only if checksum is present + - created escape_url_readable + + TODO: app_versions are currently treated as immutable by client. + Need to change this. + + todo + api/ + graphics_data.C,h + util.cpp,h + client/ + app.C + client_state.C + client_types.C + cs_files.C + file_names.C + pers_file_xfer.C,h + doc/ + api.html + boinc_dev.html + client_app.html + client_app_graphics.html + graphics.html + lib/ + parse.C,h + util.C,h + sched/ + handle_request.C + server_types.C,h diff --git a/client/app.C b/client/app.C index 62f9be074e..49891802c6 100644 --- a/client/app.C +++ b/client/app.C @@ -211,9 +211,10 @@ int ACTIVE_TASK::start(bool first_time) { // make soft links to the executable(s) // for (i=0; iapp_files.size(); i++) { - fip = app_version->app_files[i].file_info; + FILE_REF fref = app_version->app_files[i]; + fip = fref.file_info; get_pathname(fip, file_path); - if (i == 0) { + if (fref.main_program) { safe_strcpy(exec_name, fip->name); safe_strcpy(exec_path, file_path); } diff --git a/client/client_state.C b/client/client_state.C index ada393e18e..256a2a52f0 100644 --- a/client/client_state.C +++ b/client/client_state.C @@ -976,9 +976,11 @@ int CLIENT_STATE::link_app_version(PROJECT* p, APP_VERSION* avp) { return 1; } - // any file associated with an app version must be signed + // any executable file associated with an app version must be signed // - fip->signature_required = true; + if (fip->executable) { + fip->signature_required = true; + } avp->app_files[i].file_info = fip; } return 0; diff --git a/client/client_types.C b/client/client_types.C index e960eb39a7..3a8bd7260e 100644 --- a/client/client_types.C +++ b/client/client_types.C @@ -436,11 +436,16 @@ int FILE_INFO::write(FILE* out, bool to_server) { fprintf(out, "\n" " %s\n" - " %s\n" " %f\n" " %f\n", - name, md5_cksum, nbytes, max_nbytes + name, nbytes, max_nbytes ); + if (strlen(md5_cksum)) { + fprintf(out, + " %s\n", + md5_cksum + ); + } if (!to_server) { if (generated_locally) fprintf(out, " \n"); fprintf(out, " %d\n", status); diff --git a/client/cs_files.C b/client/cs_files.C index 56a0dbc64e..c29f4aaf46 100644 --- a/client/cs_files.C +++ b/client/cs_files.C @@ -103,7 +103,7 @@ int verify_downloaded_file(char* pathname, FILE_INFO& file_info) { fprintf(stderr, "error: verify_file2: file not verified\n"); return ERR_RSA_FAILED; } - } else if (file_info.md5_cksum) { + } else if (strlen(file_info.md5_cksum)) { retval = md5_file(pathname, cksum, file_info.nbytes); if (strcmp(cksum, file_info.md5_cksum) || retval) { fprintf(stderr, "error: verify_file2: MD5 check failed\n"); diff --git a/client/cs_scheduler.C b/client/cs_scheduler.C index 38076f99a0..304a657eb9 100644 --- a/client/cs_scheduler.C +++ b/client/cs_scheduler.C @@ -396,18 +396,13 @@ int CLIENT_STATE::handle_scheduler_reply( // deal with project preferences (should always be there) // if (sr.project_prefs_xml) { - strcpy(project->project_specific_prefs, sr.project_prefs_xml); - retval = project->write_account_file(); - if (retval) return retval; - -#if 0 - char path[256]; - get_account_filename(project->master_url, path); - f = fopen(path, "r"); - if (!f) return ERR_FOPEN; - project->parse_account(f); - fclose(f); -#endif + if (strcmp( + project->project_specific_prefs, sr.project_prefs_xml + )) { + strcpy(project->project_specific_prefs, sr.project_prefs_xml); + retval = project->write_account_file(); + if (retval) return retval; + } } // if the scheduler reply includes a code-signing key, diff --git a/client/file_names.C b/client/file_names.C index 25d23d945b..dd81a25f65 100644 --- a/client/file_names.C +++ b/client/file_names.C @@ -32,38 +32,8 @@ #include "file_names.h" #include "util.h" -// Escape a URL for the project directory, cutting off the "http://", -// converting '\' '/' and ' ' to '_', -// and converting the non alphanumeric characters to %XY -// where XY is their hexadecimal equivalent -// void escape_project_url(char *in, char* out) { - int x, y; - char *temp; - char buf[256]; - - temp = strstr(in,"://"); - if (temp) { - in = temp + strlen("://"); - } - for (x=0, y=0; in[x]; ++x) { - if (isalnum(in[x]) || in[x]=='.' || in[x]=='-' || in[x]=='_') { - out[y] = in[x]; - ++y; - } else if (in[x] == '/' || in[x] == '\\' || in[x] == ' ') { - out[y] = '_'; - ++y; - } else { - out[y] = '%'; - ++y; - out[y] = 0; - sprintf(buf, "%d", (char)in[x]); - c2x(buf); - strcat(out, buf); - y += 2; - } - } - out[y] = 0; + escape_url_readable(in, out); } // Gets the pathname of a file diff --git a/client/pers_file_xfer.C b/client/pers_file_xfer.C index 6761ef436f..325e0e0327 100644 --- a/client/pers_file_xfer.C +++ b/client/pers_file_xfer.C @@ -93,17 +93,21 @@ int PERS_FILE_XFER::start_xfer() { (is_upload ? "upload" : "download"), fip->get_url(), retval ); show_message(fip->project, buf, MSG_ERROR); + handle_xfer_failure(); return retval; // TODO: do we need to do anything here? } retval = gstate.file_xfers->insert(file_xfer); fxp = file_xfer; if (retval) { - if (log_flags.file_xfer) { - show_message(fip->project, "file_xfer insert failed", MSG_ERROR); - } + sprintf(buf, + "Couldn't start %s for %s: error %d", + (is_upload ? "upload" : "download"), fip->get_url(), retval + ); + show_message(fip->project, buf, MSG_ERROR); fxp->file_xfer_retval = retval; - handle_xfer_failure(time(0)); + handle_xfer_failure(); + delete fxp; fxp = NULL; return retval; } @@ -209,7 +213,7 @@ bool PERS_FILE_XFER::poll(time_t now) { } else if (fxp->file_xfer_retval == ERR_UPLOAD_PERMANENT) { giveup(); } else { - handle_xfer_failure(now); + handle_xfer_failure(); } // remove fxp from file_xfer_set and deallocate it // @@ -240,7 +244,8 @@ void PERS_FILE_XFER::giveup() { // Handle a transfer failure // -void PERS_FILE_XFER::handle_xfer_failure(time_t cur_time) { +void PERS_FILE_XFER::handle_xfer_failure() { + time_t now = time(0); // If it was a bad range request, delete the file and start over // @@ -248,11 +253,11 @@ void PERS_FILE_XFER::handle_xfer_failure(time_t cur_time) { fip->delete_file(); } - retry_or_backoff(cur_time); + retry_or_backoff(); // See if it's time to give up on the persistent file xfer // - if ((cur_time - first_request_time) > gstate.file_xfer_giveup_period) { + if ((now - first_request_time) > gstate.file_xfer_giveup_period) { giveup(); } } @@ -260,15 +265,15 @@ void PERS_FILE_XFER::handle_xfer_failure(time_t cur_time) { // Cycle to the next URL, or if we've hit all URLs in this cycle, // backoff and try again later // -void PERS_FILE_XFER::retry_or_backoff(time_t cur_time) { +void PERS_FILE_XFER::retry_or_backoff() { double exp_backoff; int backoff; struct tm *newtime; - time_t aclock; + time_t now; char buf[256]; - time(&aclock); - newtime = localtime(&aclock); + now = time(0); + newtime = localtime(&now); // Cycle to the next URL to try // @@ -286,7 +291,7 @@ void PERS_FILE_XFER::retry_or_backoff(time_t cur_time) { // PERS_RETRY_DELAY_MAX // backoff = (int)max(PERS_RETRY_DELAY_MIN, min(PERS_RETRY_DELAY_MAX, exp_backoff)); - next_request_time = cur_time + backoff; + next_request_time = now + backoff; } if (log_flags.file_xfer_debug) { sprintf(buf, diff --git a/client/pers_file_xfer.h b/client/pers_file_xfer.h index 9c64b3d842..eb6a1b2aaf 100644 --- a/client/pers_file_xfer.h +++ b/client/pers_file_xfer.h @@ -59,8 +59,8 @@ public: PERS_FILE_XFER(); int init(FILE_INFO*, bool is_file_upload); bool poll(time_t now); - void handle_xfer_failure(time_t cur_time); - void retry_or_backoff(time_t cur_time); + void handle_xfer_failure(); + void retry_or_backoff(); void giveup(); int write(FILE* fout); int parse(FILE* fin); diff --git a/doc/api.html b/doc/api.html index 6eafc14afe..aac87a769c 100644 --- a/doc/api.html +++ b/doc/api.html @@ -157,101 +157,3 @@ must get the child's CPU time, then call void boinc_child_done(double total_cpu); before forking the next child process. - - -
-

Implementation

-

-Application are executed in separate "catbox" directories, -allowing them to create and use temporary files without name conflicts. -Input and output files are kept outside the catbox. -The mappings from virtual to physical filenames use -"symbolic link" files in the catbox directory. -The name of such a file is the virtual name, -and the file contains an XML tag with the physical name. -(This scheme is used because of the lack of filesystem links in Windows.) - -

-Communication between the core client and applications -is done through XML files in the catbox directory. -Several files are used. -

-Files created by the core client, read by the app: -(Once, at start of app) -

    -
  • Symbolic link files -
  • fd_init.xml: -specifies the mappings of file descriptors (stdin/stdout/stderr) -to physical files. - -
  • init_data.xml: this contains the initialization data -returned by boinc_init() (see above), -as well as the minimum checkpoint period. -
-

-Files created by the API implementation, read by the core client: -

    -
  • -fraction_done.xml: -contains the WU fraction done and the current CPU time from start of WU. -Written by the timer routine as needed. - -
  • -checkpoint_cpu.xml -CPU time (from start of WU) at last checkpoint. -Written by checkpoint_completed. - -
-

-The API implementation uses a timer (60Hz); -the real-time clock is not available to applications. -This timer is used for several purposes: -

    -
  • To tell the app when to checkpoint; -
  • To regenerate the fraction done file -
  • To refresh graphics -
- -

-Exit status -The core client does a wait() to get the status. -boinc_finish() ends with an exit(status); -

-Accounting of CPU time: -(note: in Unix, a parent can't get the CPU time of a child -until the child exits. So we're forced to measure it in the child.) -The core passes the WU CPU time in init_data.xml. -boinc_checkpoint_done() and boinc_finish() compute the new WU CPU time, -and write it to checkpoint_cpu.xml. -The core deletes this after reading. -If on exit there is no checkpoint_cpu.xml, it means the app -called exit(0) rather than boinc_finish(). -In this case the core measures the child CPU itself. -

-The core client maintains -

-Timing of checkpoints -

-The app library maintains time_until_checkpoint, -decremented from the timer handler. -boinc_time_to_checkpoint() returns true if this is zero or less. -boinc_checkpoint_done() resets it. - -

-Maintaining fraction done and current CPU -

-These two quantities are transferred from the app library to -the core client in the file fraction_done.xml. -The parameter time_until_fraction_done_update, -passed in the initialization file, -determines how often this file is written. -It is written from the timer handler. -

-For multi-program applications, only the active application -must write the file. -The functions boinc_child_start() and boinc_child_done() -tell the app library to stop and start writing the file. -

-TO DO: this creates disk traffic. -Either figure out a way of increasing the period for users who don't -want disk access, or don't use disk files. diff --git a/doc/boinc_dev.html b/doc/boinc_dev.html index 08515246ac..752917a837 100644 --- a/doc/boinc_dev.html +++ b/doc/boinc_dev.html @@ -27,7 +27,9 @@ Core client

  • Data structures
  • Main loop logic
  • Debugging -
  • Host measurements +
  • Host measurement and identification +
  • Core client/application interaction (basic) +
  • Core client/application interaction (graphics) Scheduling server diff --git a/doc/client_app.html b/doc/client_app.html index 9a660e62bc..97e14daeaf 100644 --- a/doc/client_app.html +++ b/doc/client_app.html @@ -7,3 +7,99 @@ Explain startup files Explain shared memory mechanism in general

    Explain work-related use of shmem + + +

    +Application are executed in separate "catbox" directories, +allowing them to create and use temporary files without name conflicts. +Input and output files are kept outside the catbox. +The mappings from virtual to physical filenames use +"symbolic link" files in the catbox directory. +The name of such a file is the virtual name, +and the file contains an XML tag with the physical name. +(This scheme is used because of the lack of filesystem links in Windows.) + +

    +Communication between the core client and applications +is done through XML files in the catbox directory. +Several files are used. +

    +Files created by the core client, read by the app: +(Once, at start of app) +

      +
    • Symbolic link files +
    • fd_init.xml: +specifies the mappings of file descriptors (stdin/stdout/stderr) +to physical files. + +
    • init_data.xml: this contains the initialization data +returned by boinc_init() (see above), +as well as the minimum checkpoint period. +
    +

    +Files created by the API implementation, read by the core client: +

      +
    • +fraction_done.xml: +contains the WU fraction done and the current CPU time from start of WU. +Written by the timer routine as needed. + +
    • +checkpoint_cpu.xml +CPU time (from start of WU) at last checkpoint. +Written by checkpoint_completed. + +
    +

    +The API implementation uses a timer (60Hz); +the real-time clock is not available to applications. +This timer is used for several purposes: +

      +
    • To tell the app when to checkpoint; +
    • To regenerate the fraction done file +
    • To refresh graphics +
    + +

    +Exit status +The core client does a wait() to get the status. +boinc_finish() ends with an exit(status); +

    +Accounting of CPU time: +(note: in Unix, a parent can't get the CPU time of a child +until the child exits. So we're forced to measure it in the child.) +The core passes the WU CPU time in init_data.xml. +boinc_checkpoint_done() and boinc_finish() compute the new WU CPU time, +and write it to checkpoint_cpu.xml. +The core deletes this after reading. +If on exit there is no checkpoint_cpu.xml, it means the app +called exit(0) rather than boinc_finish(). +In this case the core measures the child CPU itself. +

    +The core client maintains +

    +Timing of checkpoints +

    +The app library maintains time_until_checkpoint, +decremented from the timer handler. +boinc_time_to_checkpoint() returns true if this is zero or less. +boinc_checkpoint_done() resets it. + +

    +Maintaining fraction done and current CPU +

    +These two quantities are transferred from the app library to +the core client in the file fraction_done.xml. +The parameter time_until_fraction_done_update, +passed in the initialization file, +determines how often this file is written. +It is written from the timer handler. +

    +For multi-program applications, only the active application +must write the file. +The functions boinc_child_start() and boinc_child_done() +tell the app library to stop and start writing the file. +

    +TO DO: this creates disk traffic. +Either figure out a way of increasing the period for users who don't +want disk access, or don't use disk files. diff --git a/doc/client_app_graphic.html b/doc/client_app_graphic.html index 08c943fbae..eb8fd15edb 100644 --- a/doc/client_app_graphic.html +++ b/doc/client_app_graphic.html @@ -3,7 +3,24 @@ TO BE WRITTEN

    -Explain graphics startup files +The graphics API uses a file graphics.xml +that is created and occasionally modified by the +core client or screensaver. +This file has the format +

    +    <graphics_info>
    +        <do_graphics/>
    +        <xsize>500</xsize>
    +        <ysize>400</ysize>
    +        <full_screen/>
    +    </graphics_info>
    +
    + +

    +The graphics API implementation uses a 60 Hz timer. +Every 0.5 sec, it sees if graphics.xml has been modified, and if so parses it. +Every 1/60 sec, it sees if it's time for a new frame, +and if so calls app_render().

    Explain graphics modes of apps

    diff --git a/doc/graphics.html b/doc/graphics.html index e45b574b49..3e268ce430 100644 --- a/doc/graphics.html +++ b/doc/graphics.html @@ -33,26 +33,3 @@ It can refer to the user name, CPU time etc. obtained from Applications that don't do graphics must also supply a dummy app_render to link with the API. boinc_draw_gl is called to draw graphics - -


    -

    Implementation

    - -

    -The graphics API uses a file graphics.xml -that is created and occasionally modified by the -core client or screensaver. -This file has the format -

    -    <graphics_info>
    -        <do_graphics/>
    -        <xsize>500</xsize>
    -        <ysize>400</ysize>
    -        <full_screen/>
    -    </graphics_info>
    -
    - -

    -The graphics API implementation uses a 60 Hz timer. -Every 0.5 sec, it sees if graphics.xml has been modified, and if so parses it. -Every 1/60 sec, it sees if it's time for a new frame, -and if so calls app_render(). diff --git a/lib/parse.C b/lib/parse.C index 96e95022ac..fb046084ba 100644 --- a/lib/parse.C +++ b/lib/parse.C @@ -204,3 +204,18 @@ void extract_venue(char* in, char* venue_name, char* out) { } } } + +// copy a line from the given string. +// kinda like fgets() when you're reading from a string +// +char* sgets(char* buf, int len, char*& in) { + char* p; + + p = strstr(in, "\n"); + if (!p) return NULL; + *p = 0; + safe_strncpy(buf, in, len); + *p = '\n'; + in = p+1; + return buf; +} diff --git a/lib/parse.h b/lib/parse.h index 6f0c863b1c..85fb0ad4f0 100644 --- a/lib/parse.h +++ b/lib/parse.h @@ -32,3 +32,4 @@ extern int copy_element_contents(FILE* in, char* end_tag, char* p, int len); extern int read_file_malloc(char* pathname, char*& str); extern void replace_element(char* buf, char* start, char* end, char* replacement); extern void extract_venue(char* in, char* venue_name, char* out); +extern char* sgets(char* buf, int len, char* &in); diff --git a/lib/util.C b/lib/util.C index ed377c12ca..ead4bd8049 100755 --- a/lib/util.C +++ b/lib/util.C @@ -291,6 +291,40 @@ void escape_url(char *in, char*out) { out[y] = 0; } +// Escape a URL for the project directory, cutting off the "http://", +// converting '\' '/' and ' ' to '_', +// and converting the non alphanumeric characters to %XY +// where XY is their hexadecimal equivalent +// +void escape_url_readable(char *in, char* out) { + int x, y; + char *temp; + char buf[256]; + + temp = strstr(in,"://"); + if (temp) { + in = temp + strlen("://"); + } + for (x=0, y=0; in[x]; ++x) { + if (isalnum(in[x]) || in[x]=='.' || in[x]=='-' || in[x]=='_') { + out[y] = in[x]; + ++y; + } else if (in[x] == '/' || in[x] == '\\' || in[x] == ' ') { + out[y] = '_'; + ++y; + } else { + out[y] = '%'; + ++y; + out[y] = 0; + sprintf(buf, "%d", (char)in[x]); + c2x(buf); + strcat(out, buf); + y += 2; + } + } + out[y] = 0; +} + void safe_strncpy(char* dst, char* src, int len) { strncpy(dst, src, len); dst[len-1]=0; diff --git a/lib/util.h b/lib/util.h index 3b6c65e5d5..4346b1a8de 100755 --- a/lib/util.h +++ b/lib/util.h @@ -29,6 +29,7 @@ extern void c2x(char *what); extern void strip_whitespace(char *str); extern void unescape_url(char *url); extern void escape_url(char *in, char*out); +extern void escape_url_readable(char* in, char* out); extern void safe_strncpy(char*, char*, int); #define safe_strcpy(x, y) safe_strncpy(x, y, sizeof(x)) #define safe_strcat(x, y) if (strlen(x)+strlen(y)\n", buf); } +void parse_project_prefs(char* prefs, vector& app_files) { + char buf[256]; + APP_FILE af; + + while (sgets(buf, 256, prefs)) { + if (match_tag(buf, "")) { + af.parse(prefs); + app_files.push_back(af); + } + } +} + +// if the user's project prefs include elements of the form +// +// X +// Y +// +// then insert appropriate elements in app_version XML doc, namely: +// +// X' +// X +// +// ... (in the element) +// +// X' +// Y +// +// where X' is the escaped version of X +// +int insert_app_file_tags(APP_VERSION& av, USER& user) { + vector app_files; + APP_FILE af; + unsigned int i; + char buf[256], namebuf[256]; + int retval; + + parse_project_prefs(user.project_prefs, app_files); + for (i=0; i\n" + " %s\n" + " %s\n" + "\n", + namebuf, af.url + ); + retval = insert_after(av.xml_doc, "", buf); + if (retval) return retval; + sprintf(buf, + " \n" + " %s\n" + " %s\n" + " \n", + namebuf, af.open_name + ); + retval = insert_after(av.xml_doc, "\n", buf); + if (retval) return retval; + } + return 0; +} + // add the given workunit to a reply. // look up its app, and make sure there's a version for this platform. // Add the app and app_version to the reply also. @@ -153,8 +215,18 @@ int add_wu_to_reply( // add the app, app_version, and workunit to the reply, // but only if they aren't already there - + // reply.insert_app_unique(*app); + + // If the user's project prefs include any tags, + // make appropriate modifications to the app_version XML + // + retval = insert_app_file_tags(*app_version, reply.user); + if (retval) { + write_log("insert_app_file_tags failed\n"); + return retval; + } + reply.insert_app_version_unique(*app_version); // add time estimate to reply diff --git a/sched/server_types.C b/sched/server_types.C index 71badcc733..1372dafe66 100644 --- a/sched/server_types.C +++ b/sched/server_types.C @@ -192,6 +192,7 @@ int SCHEDULER_REPLY::write(FILE* fout) { for (i=0; i\n", fout); fputs(code_sign_key, fout); fputs("\n", fout); } + if (strlen(code_sign_key_signature)) { fputs("\n", fout); fputs(code_sign_key_signature, fout); @@ -360,3 +365,18 @@ int HOST::parse_net_stats(FILE* fin) { } return 1; } + +int APP_FILE::parse(char*& in) { + char buf[256], ebuf[256]; + + while (sgets(buf, 256, in)) { + if (match_tag(buf, "")) return 0; + else if (parse_str(buf, "", url, sizeof(url))) continue; + else if (parse_str(buf, "", open_name, sizeof(open_name))) continue; + else { + sprintf(ebuf, "APP_FILE::parse(): unrecognized %s\n", buf); + write_log(ebuf); + } + } + return 1; +} diff --git a/sched/server_types.h b/sched/server_types.h index 29b49e7d2a..e89beeb502 100644 --- a/sched/server_types.h +++ b/sched/server_types.h @@ -85,4 +85,12 @@ struct SCHEDULER_REPLY { void insert_result(RESULT&); }; +// represents an element in user's project prefs +// +struct APP_FILE { + char url[256]; + char open_name[256]; + int parse(char*&); +}; + #endif diff --git a/todo b/todo index c7d732787d..11153ee0e9 100755 --- a/todo +++ b/todo @@ -9,7 +9,6 @@ BUGS (arranged from high to low priority) - Win GUI: line between menus and tabs - "show graphics" should not use right-click - win GUI: reduce flicker? -- on major version change, should discard any pending WUs - labels on disk graph are not clear - document and add to global prefs? start_saver