home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 August / PCWorld_2001-08_cd.bin / Komunikace / sambar / _setup.1 / general.c < prev    next >
C/C++ Source or Header  |  2001-07-01  |  12KB  |  511 lines

  1. /*
  2. ** GENERAL
  3. **
  4. **      HTTP Wrapper for General utility RPCs and Scalars.
  5. **        Scalars are executed using the <RC@scalar...> scripting
  6. **        functionality.
  7. **
  8. **
  9. **        Confidential Property of Tod Sambar
  10. **        (c) Copyright Tod Sambar 1997
  11. **        All rights reserved.
  12. **
  13. **
  14. ** Public Functions:
  15. **
  16. **        pagecount_rpc
  17. **        pagecount_scalar
  18. **
  19. **
  20. ** History:
  21. ** Chg#    Date    Description                                                Resp
  22. ** ----    -------    -------------------------------------------------------    ----
  23. **         10JUN97    Created                                                    sambar
  24. **         12JUL98    Added pragma-no cache to page counter                    sambar
  25. **         10JAN00    Added scalar sample                                        sambar
  26. */
  27.  
  28. #include    <stdio.h>
  29. #include    <stdlib.h>
  30. #include    <memory.h>
  31. #include    <ctype.h>
  32. #include    <string.h>
  33. #include    <general.h>
  34. #ifndef    WIN32
  35. #include    <unistd.h>
  36. #include    <sys/file.h>
  37. #define    stricmp        strcasecmp
  38. #endif
  39.  
  40. /*
  41. ** General RPC Commands
  42. */
  43. typedef struct general__rpcs
  44. {
  45.     SA_CHAR            *name;
  46.     SA_RPCPARAM        *params;
  47.     SA_INT            numparams;
  48.     SA_INT            auth;
  49.     SA_VOID            *func;
  50.     SA_CHAR            *descr;
  51. } GENERAL__RPCS;
  52.  
  53. static SA_RPCPARAM    pagep [] =
  54. {
  55.     { "page",     1,    "Page associated with the row counter." },
  56.     { "style",     0,    "Page style: standard | plain" }
  57. };
  58.  
  59. static GENERAL__RPCS    general_rpcs [] =
  60. {
  61.     { "pagecount",    pagep,         sizeof(pagep)/sizeof(SA_RPCPARAM),
  62.       SA_AUTHORIZATION_ALL,    (SA_VOID *)pagecount_rpc,
  63.       "Retrieve the number of hits for a page." }
  64. };
  65.  
  66. /*
  67. ** General Scalar Methods
  68. */
  69. typedef struct general__scalars
  70. {
  71.     SA_CHAR            *name;
  72.     SA_SCALARARG    *args;
  73.     SA_INT            numargs;
  74.     SA_VOID            *func;
  75.     SA_CHAR            *descr;
  76. } GENERAL__SCALARS;
  77.  
  78. static SA_SCALARARG    pagecountp [] =
  79. {
  80.     { "page",     "Page associated with the row counter." }
  81. };
  82.  
  83. static GENERAL__SCALARS    general_scalars [] =
  84. {
  85.     { "pagecount",    pagecountp,        sizeof(pagecountp)/sizeof(SA_SCALARARG),
  86.       (SA_VOID *)pagecount_scalar,
  87.       "Retrieve the number of hits for a page." }
  88. };
  89.  
  90.  
  91. /*
  92. **  GENERAL_INIT
  93. **
  94. **    Initialize the General Utility RPCS use by the Sambar Server plugins.
  95. **
  96. **
  97. **  Parameters:
  98. **    sactx        Sambar Server context
  99. **
  100. **  Returns:
  101. **    SA_SUCCEED | SA_FAIL
  102. */
  103. SA_RETCODE SA_PUBLIC
  104. general_init(sactx)
  105. SA_CTX        *sactx;
  106. {
  107.     int            i;
  108.  
  109.     /* Register the RPCs with the server                                */
  110.     for (i = 0; i < sizeof(general_rpcs) / sizeof(GENERAL__RPCS); i++)
  111.     {
  112.         if (sa_cmd_init(sactx, general_rpcs[i].name, general_rpcs[i].params,
  113.             general_rpcs[i].numparams, general_rpcs[i].auth, 
  114.             general_rpcs[i].descr, general_rpcs[i].func) != SA_SUCCEED)
  115.         {
  116.             sa_log(sactx, "Unable to initialize General Utility RPCs");
  117.             return (SA_FAIL);
  118.         } 
  119.     }
  120.  
  121.     /* Register the Scalar methods with the server                        */
  122.     for (i = 0; i < sizeof(general_scalars) / sizeof(GENERAL__SCALARS); i++)
  123.     {
  124.         if (sa_scalar_init(sactx, general_scalars[i].name, 
  125.             general_scalars[i].args, general_scalars[i].numargs, 
  126.             general_scalars[i].descr, general_scalars[i].func) != SA_SUCCEED)
  127.         {
  128.             sa_log(sactx, "Unable to initialize General Utility Scalars");
  129.             return (SA_FAIL);
  130.         } 
  131.     }
  132.  
  133.     sa_log(sactx, "General RPC and Scalar Utilities Initialized");
  134.  
  135.     return (SA_SUCCEED);
  136. }
  137.  
  138. /*
  139. **  PAGECOUNT_RPC
  140. **
  141. **    RPC to retrieve the count associated with a page.
  142. **
  143. **  Parameters:
  144. **    sactx        Sambar Server context
  145. **    saconn        Sambar Server connection
  146. **    saparams    RPC Parameters
  147. **    infop        Error parameters
  148. **
  149. **  Returns:
  150. **    SA_SUCCEED | SA_FAIL
  151. */
  152. SA_RETCODE SA_PUBLIC
  153. pagecount_rpc(sactx, saconn, saparams, infop)
  154. SA_CTX        *sactx;
  155. SA_CONN        *saconn;
  156. SA_PARAMS    *saparams;
  157. SA_INT        *infop;
  158. {
  159.     int            fh;
  160.     SA_INT        head;
  161.     SA_INT        datalen;
  162.       SA_INT         num, i, j;
  163.     SA_BOOL        plain;
  164.     SA_CHAR        *data;
  165.       SA_INT         count[INT_WIDTH + 1];
  166.     SA_CHAR     pagename[1024];
  167.     SA_CHAR        dirname[512];
  168.     SA_CHAR        buffer[256];
  169.  
  170.     plain = 0;
  171.     if (sa_param(sactx, saparams, "style", &data, &datalen) == SA_SUCCEED)
  172.     {
  173.         if ((datalen == 5) && (stricmp(data, "plain") == 0))
  174.             plain = 1;
  175.     }
  176.     
  177.     if (sa_param(sactx, saparams, "page", &data, &datalen) != SA_SUCCEED)
  178.     {
  179.         *infop = SA_E_INVALIDDATA;
  180.         sa_log(sactx, "pagecount_rpc(): Expected parameter 'page'!");
  181.         return (SA_FAIL);
  182.     }
  183.     
  184.     if ((datalen == 0) || (datalen > 40))
  185.     {
  186.         *infop = SA_E_INVALIDDATA;
  187.         sa_log(sactx, "pagecount_rpc(): 'page' field is NULL!");
  188.         return (SA_FAIL);
  189.     }
  190.  
  191.     /* Disallow pathed names (i.e. .. / ~ etc.)                            */
  192.     for (i = 0; i < datalen; i++)
  193.     {
  194.         if (!(isalnum(data[i]) || (data[i] == '_') ||
  195.             (data[i] == '-') || (data[i] == '.')))
  196.         {
  197.             *infop = SA_E_INVALIDDATA;
  198.             sa_log(sactx, 
  199.                 "pagecount_rpc(): 'page' contains invalid characters!");
  200.             return (SA_FAIL);
  201.         }
  202.  
  203.         if ((i > 0) && (data[i] == '.') && (data[i - 1] == '.'))
  204.         {
  205.             *infop = SA_E_INVALIDDATA;
  206.             sa_log(sactx, 
  207.                 "pagecount_rpc(): 'page' contains invalid characters!");
  208.             return (SA_FAIL);
  209.         }
  210.     }
  211.  
  212.  
  213.     /*
  214.     ** Open the file with the current count.
  215.     ** The file must exist or we return 0.
  216.     */
  217.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_HOMEDIR, pagename,
  218.         900, &i) != SA_SUCCEED)
  219.     {
  220.         sa_log(sactx, "pagecount_rpc(): Failure getting SA_CTXPROP_HOMEDIR!");
  221.         return (SA_FAIL);
  222.     }
  223.  
  224.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_APPLICDIR, dirname,
  225.         512, &j) != SA_SUCCEED)
  226.     {
  227.         sa_log(sactx, "pagecount_rpc(): Failure getting SA_CTXPROP_APPLICDIR!");
  228.         return (SA_FAIL);
  229.     }
  230.  
  231. #ifdef    WIN32
  232.     sprintf(&pagename[i], "\\%s\\%s", (j > 0 ? dirname : "tmp"), data);
  233. #else
  234.     if (j > 0)
  235.         sprintf(&pagename[i], "/%s/%s", dirname, data);
  236.     else
  237.         sprintf(&pagename[i], "/%s/tmp", data);
  238. #endif    /* WIN32 */
  239.  
  240.     num = 0;
  241.  
  242. #ifdef    WIN32
  243.     if ((fh = _sopen(pagename, _O_RDWR, _SH_DENYNO, _S_IREAD|_S_IWRITE)) != -1)
  244.     {
  245.         if (_locking(fh, _LK_LOCK, 1) != -1)
  246.         {
  247.             buffer[0] = '\0';
  248.             _read(fh, buffer, INT_WIDTH);
  249.             num = atol(buffer) + 1;
  250.             lseek(fh, 0L, SEEK_SET);
  251.             sprintf(buffer, "%ld\n", num);
  252.             _write(fh, buffer, strlen(buffer));
  253.             _locking(fh, _LK_UNLCK, 1);
  254.         }
  255.  
  256.         _close(fh);
  257.     }
  258. #else    /* LINUX */
  259.     /* FIX THIS sambar - need locking! */
  260.     if ((fh = open(pagename, O_RDWR)) != -1)
  261.     {
  262.         if (flock(fh, LOCK_EX) != -1)
  263.         {
  264.             buffer[0] = '\0';
  265.             read(fh, buffer, INT_WIDTH);
  266.             num = atol(buffer) + 1;
  267.             lseek(fh, 0L, SEEK_SET);
  268.             sprintf(buffer, "%ld\n", num);
  269.             write(fh, buffer, strlen(buffer));
  270.             flock(fh, LOCK_UN);
  271.         }
  272.  
  273.         close(fh);
  274.     }
  275. #endif
  276.  
  277.     /* Convert the current count to an array of numbers. */
  278.     count[INT_WIDTH] = '\0';
  279.     for (i = 0; i < INT_WIDTH; ++i) 
  280.     {
  281.         j = num % 10;
  282.         count[INT_WIDTH - 1 - i] = j;
  283.         num /= 10;
  284.     }
  285.  
  286.     /* Send HTTP header */
  287.     if (sa_send_header(saconn, "HTTP/1.0 200 OK\r\n", SA_NULLTERM) 
  288.         != SA_SUCCEED)
  289.     {
  290.         return (SA_FAIL);
  291.     }
  292.  
  293.     if (sa_conn_send(saconn, "Expires: Thu, 01 Jan 1995 01:00:00:00 GMT\r\n", 
  294.         SA_NULLTERM) != SA_SUCCEED)
  295.     {
  296.         return (SA_FAIL);
  297.     }
  298.  
  299.     if (sa_conn_send(saconn, "Pragma: no-cache\r\n", SA_NULLTERM) != SA_SUCCEED)
  300.         return (SA_FAIL);
  301.  
  302.     /* MIME type is x bitmap */
  303.     if (sa_conn_send(saconn, "Content-Type: image/x-xbitmap\r\n\r\n", 
  304.         SA_NULLTERM) != SA_SUCCEED)
  305.     {
  306.         return (SA_FAIL);
  307.     }
  308.  
  309.     /* Strip leading zeros from the 'plain' display. */
  310.     head = 0;
  311.     if (plain)
  312.     {
  313.         while ((count[head] == 0) && (head < INT_WIDTH - 1))
  314.             head++;
  315.     }
  316.  
  317.        /* print the counter definitions */
  318.        sprintf(buffer, "#define counter_width %ld\r\n", 
  319.         (INT_WIDTH - head) * COUNT_WIDTH);
  320.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  321.         return (SA_FAIL);
  322.  
  323.        sprintf(buffer, "#define counter_height %d\r\n", COUNT_HEIGHT);
  324.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  325.         return (SA_FAIL);
  326.  
  327.        /* print out the bitmap itself */
  328.     if (sa_conn_send(saconn, "static unsigned char counter_bits[] = {\r\n", 
  329.         SA_NULLTERM) != SA_SUCCEED)
  330.     {
  331.         return (SA_FAIL);
  332.     }
  333.  
  334.     if (plain)
  335.     {
  336.            for (i = 0; i < COUNT_HEIGHT; ++i) 
  337.         {
  338.             for (j = head; j < INT_WIDTH; ++j) 
  339.             {
  340.                    sprintf(buffer, "0x%02X, ", bitmap2[count[j]][i]);
  341.                 if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  342.                     return (SA_FAIL);
  343.             }
  344.         }
  345.     }
  346.     else
  347.     {
  348.            for (i = 0; i < COUNT_HEIGHT; ++i) 
  349.         {
  350.             for (j = 0; j < INT_WIDTH; ++j) 
  351.             {
  352.                    sprintf(buffer, "%s", bitmap[(count[j] * COUNT_HEIGHT) + i]);
  353.                 if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  354.                     return (SA_FAIL);
  355.     
  356.                    if (( i < COUNT_HEIGHT - 1) || (j < INT_WIDTH - 1)) 
  357.                 {
  358.                     if (sa_conn_send(saconn, ", ", SA_NULLTERM) != SA_SUCCEED)
  359.                         return (SA_FAIL);
  360.                 }
  361.             }
  362.         }
  363.  
  364.         if (sa_conn_send(saconn, "\r\n", SA_NULLTERM) != SA_SUCCEED)
  365.             return (SA_FAIL);
  366.     }
  367.  
  368.     if (sa_conn_send(saconn, "};\r\n", SA_NULLTERM) != SA_SUCCEED)
  369.         return (SA_FAIL);
  370.  
  371.     if (sa_conn_flush(saconn) != SA_SUCCEED)
  372.         return (SA_FAIL);
  373.  
  374.     return (SA_SUCCEED);
  375. }
  376.  
  377. /*
  378. **  PAGECOUNT_SCALAR
  379. **
  380. **    Scalar to retrieve the count associated with a page.
  381. **    Operates identically to the pagecount RPC except only
  382. **    ASCII text is output.
  383. **
  384. **    Usage:    <RC@pagecount(index)>
  385. **
  386. **  Parameters:
  387. **    sactx        Sambar Server context
  388. **    saconn        Sambar Server connection
  389. **    saargs        Scalar arguments
  390. **    value        Result buffer (maximum 1000 bytes).
  391. **
  392. **  Returns:
  393. **    SA_SUCCEED | SA_FAIL
  394. */
  395. SA_RETCODE SA_PUBLIC
  396. pagecount_scalar(sactx, saconn, saargs, value)
  397. SA_CTX        *sactx;
  398. SA_CONN        *saconn;
  399. SA_ARG        *saargs;
  400. SA_CHAR        *value;
  401. {
  402.     int            fh;
  403.       SA_INT         num, i, j;
  404.     SA_INT        datalen;
  405.     SA_CHAR        *data;
  406.     SA_CHAR     pagename[1024];
  407.     SA_CHAR        dirname[512];
  408.     SA_CHAR        buffer[256];
  409.  
  410.     data = saargs->value;
  411.     if (data != NULL)
  412.         datalen = strlen(data);
  413.     else
  414.         datalen = 0;
  415.  
  416.     if ((datalen == 0) || (datalen > 40))
  417.     {
  418.         sa_log(sactx, "pagecount_scalar(): 'page' field is NULL!");
  419.         return (SA_FAIL);
  420.     }
  421.  
  422.     /* Disallow pathed names (i.e. .. / ~ etc.)                            */
  423.     for (i = 0; i < datalen; i++)
  424.     {
  425.         if (!(isalnum(data[i]) || (data[i] == '_') ||
  426.             (data[i] == '-') || (data[i] == '.')))
  427.         {
  428.             sa_log(sactx, 
  429.                 "pagecount_rpc(): 'page' contains invalid characters!");
  430.             return (SA_FAIL);
  431.         }
  432.  
  433.         if ((i > 0) && (data[i] == '.') && (data[i - 1] == '.'))
  434.         {
  435.             sa_log(sactx, 
  436.                 "pagecount_rpc(): 'page' contains invalid characters!");
  437.             return (SA_FAIL);
  438.         }
  439.     }
  440.  
  441.     /*
  442.     ** Open the file with the current count.
  443.     ** The file must exist or we return 0.
  444.     */
  445.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_HOMEDIR, pagename,
  446.         900, &i) != SA_SUCCEED)
  447.     {
  448.         sa_log(sactx, 
  449.             "pagecount_scalar(): Failure getting SA_CTXPROP_HOMEDIR!");
  450.         return (SA_FAIL);
  451.     }
  452.  
  453.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_APPLICDIR, dirname,
  454.         512, &j) != SA_SUCCEED)
  455.     {
  456.         sa_log(sactx, 
  457.             "pagecount_scalar(): Failure getting SA_CTXPROP_APPLICDIR!");
  458.         return (SA_FAIL);
  459.     }
  460.  
  461. #ifdef    WIN32
  462.     sprintf(&pagename[i], "\\%s\\%s", (j > 0 ? dirname : "tmp"), data);
  463. #else
  464.     if (j > 0)
  465.         sprintf(&pagename[i], "/%s/%s", dirname, data);
  466.     else
  467.         sprintf(&pagename[i], "/%s/tmp", data);
  468. #endif    /* WIN32 */
  469.  
  470.     num = 0;
  471.  
  472. #ifdef    WIN32
  473.     if ((fh = _sopen(pagename, _O_RDWR, _SH_DENYNO, _S_IREAD|_S_IWRITE)) != -1)
  474.     {
  475.         if (_locking(fh, _LK_LOCK, 1) != -1)
  476.         {
  477.             buffer[0] = '\0';
  478.             _read(fh, buffer, INT_WIDTH);
  479.             num = atol(buffer) + 1;
  480.             lseek(fh, 0L, SEEK_SET);
  481.             sprintf(buffer, "%ld\n", num);
  482.             _write(fh, buffer, strlen(buffer));
  483.             _locking(fh, _LK_UNLCK, 1);
  484.         }
  485.  
  486.         _close(fh);
  487.     }
  488. #else    /* LINUX */
  489.     /* FIX THIS sambar - need locking! */
  490.     if ((fh = open(pagename, O_RDWR)) != -1)
  491.     {
  492.         if (flock(fh, LOCK_EX) != -1)
  493.         {
  494.             buffer[0] = '\0';
  495.             read(fh, buffer, INT_WIDTH);
  496.             num = atol(buffer) + 1;
  497.             lseek(fh, 0L, SEEK_SET);
  498.             sprintf(buffer, "%ld\n", num);
  499.             write(fh, buffer, strlen(buffer));
  500.             flock(fh, LOCK_UN);
  501.         }
  502.  
  503.         close(fh);
  504.     }
  505. #endif
  506.  
  507.     /* Return the count in the scalar 'value' output buffer            */
  508.     sprintf(value, "%ld", num);
  509.     return (SA_SUCCEED);
  510. }
  511.