static int cmd_codecs_proc()

in nshlib/nsh_codeccmd.c [234:515]


static int cmd_codecs_proc(FAR struct nsh_vtbl_s *vtbl, int argc,
                           FAR char **argv, uint8_t mode,
                           codec_callback_t func)
{
#ifdef HAVE_CODECS_HASH_MD5
  static const unsigned char hexchars[] = "0123456789abcdef";
  MD5_CTX ctx;
  unsigned char mac[16];
  FAR unsigned char *src;
  FAR char *dest;
#endif

  FAR char *localfile = NULL;
  FAR char *srcbuf = NULL;
  FAR char *destbuf = NULL;
  FAR char *fullpath = NULL;
  FAR const char *fmt;
  FAR char *sdata;
  bool badarg = false;
  bool isfile = false;
  bool iswebsafe = false;
  int option;
  int fd = -1;
  int buflen = 0;
  int srclen = 0;
  int ret = OK;

  /* Get the command options */

  while ((option = getopt(argc, argv, ":fw")) != ERROR)
    {
      switch (option)
        {
          case 'f':
            isfile = true;
            break;

#ifdef CONFIG_CODECS_BASE64
          case 'w':
            iswebsafe = true;

            if (!(mode == CODEC_MODE_BASE64ENC ||
                  mode == CODEC_MODE_BASE64DEC))
              {
                badarg = true;
              }
            break;
#endif
          case ':':
            nsh_error(vtbl, g_fmtargrequired, argv[0]);
            badarg = true;
            break;

          case '?':
          default:
            nsh_error(vtbl, g_fmtarginvalid, argv[0]);
            badarg = true;
            break;
        }
    }

  /* If a bad argument was encountered, then return without processing
   * the command
   */

  if (badarg)
    {
      return ERROR;
    }

  /* There should be exactly on parameter left on the command-line */

  if (optind == argc - 1)
    {
      sdata = argv[optind];
    }
  else if (optind < argc)
    {
      fmt = g_fmttoomanyargs;
      goto errout;
    }
  else
    {
      fmt = g_fmtargrequired;
      goto errout;
    }

#ifdef HAVE_CODECS_HASH_MD5
  if (mode == CODEC_MODE_HASH_MD5)
    {
      md5_init(&ctx);
    }
#endif

  if (isfile)
    {
      /* Get the local file name */

      localfile = sdata;

      /* Get the full path to the local file */

      fullpath = nsh_getfullpath(vtbl, localfile);

      /* Open the local file for reading */

      fd = open(fullpath, O_RDONLY);
      if (fd < 0)
        {
          nsh_error(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
          ret = ERROR;
          goto exit;
        }

      srcbuf = malloc(CONFIG_NSH_CODECS_BUFSIZE + 2);
      if (!srcbuf)
        {
          fmt = g_fmtcmdoutofmemory;
          goto errout;
        }

#ifdef HAVE_CODECS_BASE64ENC
      if (mode == CODEC_MODE_BASE64ENC)
        {
          srclen = CONFIG_NSH_CODECS_BUFSIZE / 3 * 3;
        }
      else
#endif
        {
          srclen = CONFIG_NSH_CODECS_BUFSIZE;
        }

      buflen = calc_codec_buffsize(srclen + 2, mode);
      destbuf = malloc(buflen);
      if (!destbuf)
        {
          fmt = g_fmtcmdoutofmemory;
          goto errout;
        }

      while (true)
        {
          memset(srcbuf, 0, srclen + 2);
          ret = read(fd, srcbuf, srclen);
          if (ret < 0)
            {
              nsh_error(vtbl, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO);
              ret = ERROR;
              goto exit;
            }
          else if (ret == 0)
            {
              break;
            }

#ifdef HAVE_CODECS_URLDECODE
          if (mode == CODEC_MODE_URLDECODE)
            {
              if (srcbuf[srclen - 1] == '%')
                {
                  ret += read(fd, &srcbuf[srclen], 2);
                }
              else if (srcbuf[srclen - 2] == '%')
                {
                  ret += read(fd, &srcbuf[srclen], 1);
                }
            }

#endif
          memset(destbuf, 0, buflen);
          if (func)
            {
#ifdef HAVE_CODECS_HASH_MD5
              if (mode == CODEC_MODE_HASH_MD5)
                {
                  func(srcbuf, ret, (char *)&ctx, &buflen, 0);
                }
              else
#endif
                {
                  func(srcbuf, ret, destbuf, &buflen, iswebsafe ? 1 : 0);
                  nsh_output(vtbl, "%s", destbuf);
                }
            }

          buflen = calc_codec_buffsize(srclen + 2, mode);
        }

#ifdef HAVE_CODECS_HASH_MD5
      if (mode == CODEC_MODE_HASH_MD5)
        {
          int i;

          md5_final(mac, &ctx);
          src  = mac;
          dest = destbuf;
          for (i = 0; i < 16; i++, src++)
            {
              *dest++ = hexchars[(*src) >> 4];
              *dest++ = hexchars[(*src) & 0x0f];
            }

          *dest = '\0';
          nsh_output(vtbl, "%s\n", destbuf);
        }

#endif
      ret = OK;
      goto exit;
    }
  else
    {
      srcbuf  = sdata;
      srclen  = strlen(sdata);
      buflen  = calc_codec_buffsize(srclen, mode);
      destbuf = malloc(buflen);
      if (!destbuf)
        {
          fmt = g_fmtcmdoutofmemory;
          goto errout;
        }

      memset(destbuf, 0, buflen);
      if (func)
        {
#ifdef HAVE_CODECS_HASH_MD5
          if (mode == CODEC_MODE_HASH_MD5)
            {
              int i;

              func(srcbuf, srclen, (char *)&ctx, &buflen, 0);
              md5_final(mac, &ctx);
              src  = mac;
              dest = destbuf;
              for (i = 0; i < 16; i++, src++)
                {
                  *dest++ = hexchars[(*src) >> 4];
                  *dest++ = hexchars[(*src) & 0x0f];
                }

              *dest = '\0';
            }
          else
#endif
            {
              func(srcbuf, srclen, destbuf, &buflen, iswebsafe ? 1 : 0);
            }
        }

      nsh_output(vtbl, "%s\n", destbuf);
      srcbuf = NULL;
      goto exit;
    }

exit:
  if (fd >= 0)
    {
      close(fd);
    }

  if (fullpath)
    {
      free(fullpath);
    }

  if (srcbuf)
    {
      free(srcbuf);
    }

  if (destbuf)
    {
      free(destbuf);
    }

  return ret;

errout:
  nsh_output(vtbl, fmt, argv[0]);
  ret = ERROR;
  goto exit;
}