home *** CD-ROM | disk | FTP | other *** search
/ PC World 2002 May / PCWorld_2002-05_cd.bin / Komunik / sambar / sambar51p.exe / samples / source / general.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-12-09  |  11.9 KB  |  527 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_log2(sactx, SA_LOG_ERROR, 
  117.                 "Unable to initialize General Utility RPCs");
  118.             return (SA_FAIL);
  119.         } 
  120.     }
  121.  
  122.     /* Register the Scalar methods with the server                        */
  123.     for (i = 0; i < sizeof(general_scalars) / sizeof(GENERAL__SCALARS); i++)
  124.     {
  125.         if (sa_scalar_init(sactx, general_scalars[i].name, 
  126.             general_scalars[i].args, general_scalars[i].numargs, 
  127.             general_scalars[i].descr, general_scalars[i].func) != SA_SUCCEED)
  128.         {
  129.             sa_log2(sactx, SA_LOG_ERROR,
  130.                 "Unable to initialize General Utility Scalars");
  131.             return (SA_FAIL);
  132.         } 
  133.     }
  134.  
  135.     sa_log2(sactx, SA_LOG_TRACE,
  136.         "General RPC and Scalar Utilities Initialized");
  137.  
  138.     return (SA_SUCCEED);
  139. }
  140.  
  141. /*
  142. **  PAGECOUNT_RPC
  143. **
  144. **    RPC to retrieve the count associated with a page.
  145. **
  146. **  Parameters:
  147. **    sactx        Sambar Server context
  148. **    saconn        Sambar Server connection
  149. **    saparams    RPC Parameters
  150. **    infop        Error parameters
  151. **
  152. **  Returns:
  153. **    SA_SUCCEED | SA_FAIL
  154. */
  155. SA_RETCODE SA_PUBLIC
  156. pagecount_rpc(sactx, saconn, saparams, infop)
  157. SA_CTX        *sactx;
  158. SA_CONN        *saconn;
  159. SA_PARAMS    *saparams;
  160. SA_INT        *infop;
  161. {
  162.     int            fh;
  163.     SA_INT        head;
  164.     SA_INT        datalen;
  165.       SA_INT         num, i, j;
  166.     SA_BOOL        plain;
  167.     SA_CHAR        *data;
  168.       SA_INT         count[INT_WIDTH + 1];
  169.     SA_CHAR     pagename[1024];
  170.     SA_CHAR        dirname[512];
  171.     SA_CHAR        buffer[256];
  172.  
  173.     plain = 0;
  174.     if (sa_param(sactx, saparams, "style", &data, &datalen) == SA_SUCCEED)
  175.     {
  176.         if ((datalen == 5) && (stricmp(data, "plain") == 0))
  177.             plain = 1;
  178.     }
  179.     
  180.     if (sa_param(sactx, saparams, "page", &data, &datalen) != SA_SUCCEED)
  181.     {
  182.         *infop = SA_E_INVALIDDATA;
  183.         sa_log2(sactx, SA_LOG_WARN,
  184.             "pagecount_rpc(): Expected parameter 'page'!");
  185.         return (SA_FAIL);
  186.     }
  187.     
  188.     if ((datalen == 0) || (datalen > 40))
  189.     {
  190.         *infop = SA_E_INVALIDDATA;
  191.         sa_log2(sactx, SA_LOG_WARN, "pagecount_rpc(): 'page' field is NULL!");
  192.         return (SA_FAIL);
  193.     }
  194.  
  195.     /* Disallow pathed names (i.e. .. / ~ etc.)                            */
  196.     for (i = 0; i < datalen; i++)
  197.     {
  198.         if (!(isalnum(data[i]) || (data[i] == '_') ||
  199.             (data[i] == '-') || (data[i] == '.')))
  200.         {
  201.             *infop = SA_E_INVALIDDATA;
  202.             sa_log2(sactx, SA_LOG_WARN, 
  203.                 "pagecount_rpc(): 'page' contains invalid characters!");
  204.             return (SA_FAIL);
  205.         }
  206.  
  207.         if ((i > 0) && (data[i] == '.') && (data[i - 1] == '.'))
  208.         {
  209.             *infop = SA_E_INVALIDDATA;
  210.             sa_log2(sactx, SA_LOG_WARN, 
  211.                 "pagecount_rpc(): 'page' contains invalid characters!");
  212.             return (SA_FAIL);
  213.         }
  214.     }
  215.  
  216.  
  217.     /*
  218.     ** Open the file with the current count.
  219.     ** The file must exist or we return 0.
  220.     */
  221.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_HOMEDIR, pagename,
  222.         900, &i) != SA_SUCCEED)
  223.     {
  224.         sa_log2(sactx, SA_LOG_WARN,
  225.             "pagecount_rpc(): Failure getting SA_CTXPROP_HOMEDIR!");
  226.         return (SA_FAIL);
  227.     }
  228.  
  229.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_APPLICDIR, dirname,
  230.         512, &j) != SA_SUCCEED)
  231.     {
  232.         sa_log2(sactx, SA_LOG_WARN,
  233.             "pagecount_rpc(): Failure getting SA_CTXPROP_APPLICDIR!");
  234.         return (SA_FAIL);
  235.     }
  236.  
  237. #ifdef    WIN32
  238.     sprintf(&pagename[i], "\\%s\\%s", (j > 0 ? dirname : "tmp"), data);
  239. #else
  240.     if (j > 0)
  241.         sprintf(&pagename[i], "/%s/%s", dirname, data);
  242.     else
  243.         sprintf(&pagename[i], "/%s/tmp", data);
  244. #endif    /* WIN32 */
  245.  
  246.     num = 0;
  247.  
  248. #ifdef    WIN32
  249.     if ((fh = _sopen(pagename, _O_RDWR, _SH_DENYNO, _S_IREAD|_S_IWRITE)) != -1)
  250.     {
  251.         if (_locking(fh, _LK_LOCK, 1) != -1)
  252.         {
  253.             buffer[0] = '\0';
  254.             _read(fh, buffer, INT_WIDTH);
  255.             num = atol(buffer) + 1;
  256.             lseek(fh, 0L, SEEK_SET);
  257.             sprintf(buffer, "%ld\n", num);
  258.             _write(fh, buffer, strlen(buffer));
  259.             _locking(fh, _LK_UNLCK, 1);
  260.         }
  261.  
  262.         _close(fh);
  263.     }
  264. #else    /* LINUX */
  265.     /* FIX THIS sambar - need locking! */
  266.     if ((fh = open(pagename, O_RDWR)) != -1)
  267.     {
  268.         if (flock(fh, LOCK_EX) != -1)
  269.         {
  270.             buffer[0] = '\0';
  271.             read(fh, buffer, INT_WIDTH);
  272.             num = atol(buffer) + 1;
  273.             lseek(fh, 0L, SEEK_SET);
  274.             sprintf(buffer, "%ld\n", num);
  275.             write(fh, buffer, strlen(buffer));
  276.             flock(fh, LOCK_UN);
  277.         }
  278.  
  279.         close(fh);
  280.     }
  281. #endif
  282.  
  283.     /* Convert the current count to an array of numbers. */
  284.     count[INT_WIDTH] = '\0';
  285.     for (i = 0; i < INT_WIDTH; ++i) 
  286.     {
  287.         j = num % 10;
  288.         count[INT_WIDTH - 1 - i] = j;
  289.         num /= 10;
  290.     }
  291.  
  292.     /* Send HTTP header */
  293.     if (sa_send_header(saconn, "HTTP/1.0 200 OK\r\n", SA_NULLTERM) 
  294.         != SA_SUCCEED)
  295.     {
  296.         return (SA_FAIL);
  297.     }
  298.  
  299.     if (sa_conn_send(saconn, "Expires: Thu, 01 Jan 1995 01:00:00:00 GMT\r\n", 
  300.         SA_NULLTERM) != SA_SUCCEED)
  301.     {
  302.         return (SA_FAIL);
  303.     }
  304.  
  305.     if (sa_conn_send(saconn, "Pragma: no-cache\r\n", SA_NULLTERM) 
  306.         != SA_SUCCEED)
  307.     {
  308.         return (SA_FAIL);
  309.     }
  310.  
  311.     if (sa_conn_send(saconn, "Connection: close\r\n", SA_NULLTERM) 
  312.         != SA_SUCCEED)
  313.     {
  314.         return (SA_FAIL);
  315.     }
  316.  
  317.     /* MIME type is x bitmap */
  318.     if (sa_conn_send(saconn, "Content-Type: image/x-xbitmap\r\n\r\n", 
  319.         SA_NULLTERM) != SA_SUCCEED)
  320.     {
  321.         return (SA_FAIL);
  322.     }
  323.  
  324.     /* Strip leading zeros from the 'plain' display. */
  325.     head = 0;
  326.     if (plain)
  327.     {
  328.         while ((count[head] == 0) && (head < INT_WIDTH - 1))
  329.             head++;
  330.     }
  331.  
  332.        /* print the counter definitions */
  333.        sprintf(buffer, "#define counter_width %ld\r\n", 
  334.         (INT_WIDTH - head) * COUNT_WIDTH);
  335.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  336.         return (SA_FAIL);
  337.  
  338.        sprintf(buffer, "#define counter_height %d\r\n", COUNT_HEIGHT);
  339.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  340.         return (SA_FAIL);
  341.  
  342.        /* print out the bitmap itself */
  343.     if (sa_conn_send(saconn, "static unsigned char counter_bits[] = {\r\n", 
  344.         SA_NULLTERM) != SA_SUCCEED)
  345.     {
  346.         return (SA_FAIL);
  347.     }
  348.  
  349.     if (plain)
  350.     {
  351.            for (i = 0; i < COUNT_HEIGHT; ++i) 
  352.         {
  353.             for (j = head; j < INT_WIDTH; ++j) 
  354.             {
  355.                    sprintf(buffer, "0x%02X, ", bitmap2[count[j]][i]);
  356.                 if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  357.                     return (SA_FAIL);
  358.             }
  359.         }
  360.     }
  361.     else
  362.     {
  363.            for (i = 0; i < COUNT_HEIGHT; ++i) 
  364.         {
  365.             for (j = 0; j < INT_WIDTH; ++j) 
  366.             {
  367.                    sprintf(buffer, "%s", bitmap[(count[j] * COUNT_HEIGHT) + i]);
  368.                 if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  369.                     return (SA_FAIL);
  370.     
  371.                    if (( i < COUNT_HEIGHT - 1) || (j < INT_WIDTH - 1)) 
  372.                 {
  373.                     if (sa_conn_send(saconn, ", ", SA_NULLTERM) != SA_SUCCEED)
  374.                         return (SA_FAIL);
  375.                 }
  376.             }
  377.         }
  378.  
  379.         if (sa_conn_send(saconn, "\r\n", SA_NULLTERM) != SA_SUCCEED)
  380.             return (SA_FAIL);
  381.     }
  382.  
  383.     if (sa_conn_send(saconn, "};\r\n", SA_NULLTERM) != SA_SUCCEED)
  384.         return (SA_FAIL);
  385.  
  386.     if (sa_conn_flush(saconn) != SA_SUCCEED)
  387.         return (SA_FAIL);
  388.  
  389.     return (SA_SUCCEED);
  390. }
  391.  
  392. /*
  393. **  PAGECOUNT_SCALAR
  394. **
  395. **    Scalar to retrieve the count associated with a page.
  396. **    Operates identically to the pagecount RPC except only
  397. **    ASCII text is output.
  398. **
  399. **    Usage:    <RC@pagecount(index)>
  400. **
  401. **  Parameters:
  402. **    sactx        Sambar Server context
  403. **    saconn        Sambar Server connection
  404. **    saargs        Scalar arguments
  405. **    value        Result buffer (maximum 1000 bytes).
  406. **
  407. **  Returns:
  408. **    SA_SUCCEED | SA_FAIL
  409. */
  410. SA_RETCODE SA_PUBLIC
  411. pagecount_scalar(sactx, saconn, saargs, value)
  412. SA_CTX        *sactx;
  413. SA_CONN        *saconn;
  414. SA_ARG        *saargs;
  415. SA_CHAR        *value;
  416. {
  417.     int            fh;
  418.       SA_INT         num, i, j;
  419.     SA_INT        datalen;
  420.     SA_CHAR        *data;
  421.     SA_CHAR     pagename[1024];
  422.     SA_CHAR        dirname[512];
  423.     SA_CHAR        buffer[256];
  424.  
  425.     data = saargs->value;
  426.     if (data != NULL)
  427.         datalen = strlen(data);
  428.     else
  429.         datalen = 0;
  430.  
  431.     if ((datalen == 0) || (datalen > 40))
  432.     {
  433.         sa_log2(sactx, SA_LOG_WARN,
  434.             "pagecount_scalar(): 'page' field is NULL!");
  435.         return (SA_FAIL);
  436.     }
  437.  
  438.     /* Disallow pathed names (i.e. .. / ~ etc.)                            */
  439.     for (i = 0; i < datalen; i++)
  440.     {
  441.         if (!(isalnum(data[i]) || (data[i] == '_') ||
  442.             (data[i] == '-') || (data[i] == '.')))
  443.         {
  444.             sa_log2(sactx, SA_LOG_WARN, 
  445.                 "pagecount_rpc(): 'page' contains invalid characters!");
  446.             return (SA_FAIL);
  447.         }
  448.  
  449.         if ((i > 0) && (data[i] == '.') && (data[i - 1] == '.'))
  450.         {
  451.             sa_log2(sactx, SA_LOG_WARN,
  452.                 "pagecount_rpc(): 'page' contains invalid characters!");
  453.             return (SA_FAIL);
  454.         }
  455.     }
  456.  
  457.     /*
  458.     ** Open the file with the current count.
  459.     ** The file must exist or we return 0.
  460.     */
  461.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_HOMEDIR, pagename,
  462.         900, &i) != SA_SUCCEED)
  463.     {
  464.         sa_log2(sactx, SA_LOG_WARN,
  465.             "pagecount_scalar(): Failure getting SA_CTXPROP_HOMEDIR!");
  466.         return (SA_FAIL);
  467.     }
  468.  
  469.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_APPLICDIR, dirname,
  470.         512, &j) != SA_SUCCEED)
  471.     {
  472.         sa_log2(sactx, SA_LOG_WARN,
  473.             "pagecount_scalar(): Failure getting SA_CTXPROP_APPLICDIR!");
  474.         return (SA_FAIL);
  475.     }
  476.  
  477. #ifdef    WIN32
  478.     sprintf(&pagename[i], "\\%s\\%s", (j > 0 ? dirname : "tmp"), data);
  479. #else
  480.     if (j > 0)
  481.         sprintf(&pagename[i], "/%s/%s", dirname, data);
  482.     else
  483.         sprintf(&pagename[i], "/%s/tmp", data);
  484. #endif    /* WIN32 */
  485.  
  486.     num = 0;
  487.  
  488. #ifdef    WIN32
  489.     if ((fh = _sopen(pagename, _O_RDWR, _SH_DENYNO, _S_IREAD|_S_IWRITE)) != -1)
  490.     {
  491.         if (_locking(fh, _LK_LOCK, 1) != -1)
  492.         {
  493.             buffer[0] = '\0';
  494.             _read(fh, buffer, INT_WIDTH);
  495.             num = atol(buffer) + 1;
  496.             lseek(fh, 0L, SEEK_SET);
  497.             sprintf(buffer, "%ld\n", num);
  498.             _write(fh, buffer, strlen(buffer));
  499.             _locking(fh, _LK_UNLCK, 1);
  500.         }
  501.  
  502.         _close(fh);
  503.     }
  504. #else    /* LINUX */
  505.     /* FIX THIS sambar - need locking! */
  506.     if ((fh = open(pagename, O_RDWR)) != -1)
  507.     {
  508.         if (flock(fh, LOCK_EX) != -1)
  509.         {
  510.             buffer[0] = '\0';
  511.             read(fh, buffer, INT_WIDTH);
  512.             num = atol(buffer) + 1;
  513.             lseek(fh, 0L, SEEK_SET);
  514.             sprintf(buffer, "%ld\n", num);
  515.             write(fh, buffer, strlen(buffer));
  516.             flock(fh, LOCK_UN);
  517.         }
  518.  
  519.         close(fh);
  520.     }
  521. #endif
  522.  
  523.     /* Return the count in the scalar 'value' output buffer            */
  524.     sprintf(value, "%ld", num);
  525.     return (SA_SUCCEED);
  526. }
  527.