convert:圖片轉pdf失敗


 造冰箱的大熊貓@cnblogs 2019/1/21

 

1、環境

操作系統/Ubuntu 16.04.5 LTS,內核/4.15.0-43-generic,convert/ImageMagick 6.8.9-9

 

2、問題

使用convert命令將一個jpeg格式的圖片文件轉換為pdf文檔時,提示“convert: not authorized `1.pdf` @ error/constitute.c/WriteImage/1028”錯誤。

$ convert 1.jpg 1.pdf
convert: not authorized `1.pdf` @ error/constitute.c/WriteImage/1028.
$

 

3、分析

不關心問題原因的,可以跳過這部分直接跳到下面的“4、排除故障”。

從sourceforge下載ImageMagick的源代碼壓縮包(版本6.8.9-10,沒找到6.8.9-9的源代碼)[1]。解壓縮獲得源代碼。

根據錯誤信息,在源代碼“magick”目錄下打開“constitute.c”文件,並跳轉到該文件的1028行(下面代碼中第6行)。從代碼中可以看到,錯誤是由於IsRightsAuthorized()函數返回錯誤導致的。

  domain=CoderPolicyDomain;
  rights=WritePolicyRights;
  if (IsRightsAuthorized(domain,rights,write_info->magick) == MagickFalse)
    {
      sans_exception=DestroyExceptionInfo(sans_exception);
      write_info=DestroyImageInfo(write_info);
      errno=EPERM;
      ThrowBinaryException(PolicyError,"NotAuthorized",filename);
    }

 打開“policy.c” 文件,找到IsRightsAuthorized()函數的代碼(如下所示),判斷函數返回失敗(MagickFalse)是由於給定的PolicyDomian和PoicyRights與policy_cache中的值不匹配導致的。

MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
  const PolicyRights rights,const char *pattern)
{
  const PolicyInfo
    *policy_info;

  ExceptionInfo
    *exception;

  MagickBooleanType
    authorized;

  register PolicyInfo
    *p;

  (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
    "Domain: %s; rights=%s; pattern=\"%s\" ...",
    CommandOptionToMnemonic(MagickPolicyDomainOptions,domain),
    CommandOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
  exception=AcquireExceptionInfo();
  policy_info=GetPolicyInfo("*",exception);
  exception=DestroyExceptionInfo(exception);
  if (policy_info == (PolicyInfo *) NULL)
    return(MagickTrue);
  authorized=MagickTrue;
  LockSemaphoreInfo(policy_semaphore);
  ResetLinkedListIterator(policy_cache);
  p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
  while ((p != (PolicyInfo *) NULL) && (authorized != MagickFalse))
  {
    if ((p->domain == domain) &&
        (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
      {
        if (((rights & ReadPolicyRights) != 0) &&
            ((p->rights & ReadPolicyRights) == 0))
          authorized=MagickFalse;
        if (((rights & WritePolicyRights) != 0) &&
            ((p->rights & WritePolicyRights) == 0))
          authorized=MagickFalse;
        if (((rights & ExecutePolicyRights) != 0) &&
            ((p->rights & ExecutePolicyRights) == 0))
          authorized=MagickFalse;
      }
    p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
  }
  UnlockSemaphoreInfo(policy_semaphore);
  return(authorized);
}

 在該文件中繼續搜索,發現policy_cache由IsPolicyCacheInstantiated()函數從PolicyFilename指向的文件中讀取。而PolicyFilename為“policy.xml”(#define PolicyFilename  "policy.xml")。

static MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
{
  if (policy_cache == (LinkedListInfo *) NULL)
    {
      if (policy_semaphore == (SemaphoreInfo *) NULL)
        ActivateSemaphoreInfo(&policy_semaphore);
      LockSemaphoreInfo(policy_semaphore);
      if (policy_cache == (LinkedListInfo *) NULL)
        policy_cache=AcquirePolicyCache(PolicyFilename,exception);
      UnlockSemaphoreInfo(policy_semaphore);
    }
  return(policy_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
}

在“/etc/ImageMagick-6”下搜索到“policy.xml”文件。根據該文件中給出的注釋信息,pdf文件的權限被設置為“none”,要想獲得寫權限,需增加“write”權限。具體操作步驟參考“4、排除故障”。

在policy.xml禁止pdf寫權限是在Ubuntu的某次安全性升級時實施的[2],具體與imagemagickluanchpad的安全策略相關[ 3]。沒仔細研究到底是什么情況,有興趣的研究明白的請告知。

 

4、排除故障

使用文件編輯器打開“/etc/ImageMagick-6/policy.xml”,找到類似“<policy domain="coder" rights="none" pattern="PDF" />”的一行,將其中的“none”改為“write”,保存文件。重新執行convert命令即可。

 

參考

[1] ImageMagick 6.8.9源代碼 @ sourceforge

[2] imagemagick change log "disable ghostscript handled types by default in policy.xml" @ lunchpad.net

[3] security policy說明 @ imagemagick


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM