o
    Hii                     @   s@  d Z ddlZddlZddlZddlZddlmZ ddlmZ dd Zdd Z	d	d
 Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zd@ddZdd Zd@ddZdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd@d+d,Zd-d. Zd/d0 Zd1d2 Zd3d4 Zd5d6 Z d7d8 Z!d9d: Z"d;d< Z#d=d> Z$e%d?kre  dS dS )AuW   
替换指定文件中的特定字符串
支持JSON文件、plist文件等多种格式
    N)oc_util)oc_yamlc                 C   s    t dd| } t dd| } | S )u   
    移除JSON字符串中的尾随逗号，使其符合标准JSON格式
    支持处理对象和数组中的尾随逗号
    z,\s*}}z,\s*]])resub)json_string r	   E/data/storage/obfuscation/tool/ObjectiveC/oc_custom/custom_replace.pyremove_trailing_commas   s   r   c                 C   sj   t | ddd}| }W d   n1 sw   Y  zt|W S  tjy4   t|}t| Y S w )u/   
    读取JSON文件，容忍尾随逗号
    rutf-8encodingN)openreadjsonloadsJSONDecodeErrorr   )	file_pathfcontentcleaned_contentr	   r	   r
   load_json_with_trailing_comma   s   
r   c              
   C   s   z,t j| \}}| }|dkrt| |||W S |dkr%t| |||W S t| |||W S  tyI } ztd|  d|  W Y d}~dS d}~ww )uF  
    在指定文件中查找并替换特定字符串

    参数:
        file_path (str): 文件路径
        search_key (str): 要查找的键名，如 'xxpk_startid'
        old_value (str): 要替换的旧值
        new_value (str): 新的值

    返回:
        bool: 操作成功返回 True，否则返回 False
    .json.plist   处理文件     时出错: NF)	ospathsplitextlowerreplace_in_json_filereplace_in_plist_filereplace_in_text_file	Exceptionprint)r   
search_key	old_value	new_value_exter	   r	   r
   replace_in_file(   s   r-   c              
   C   s   z9t | }t||||}|r7t| ddd}tj||dd W d   n1 s(w   Y  td|   W dS W d	S  tyN   td
|   td Y d	S  tyj } ztd|  d|  W Y d}~d	S d}~ww )u8   
    在JSON文件中查找并替换特定键的值
    wr   r      indentN   已更新JSON文件: TFu   错误: 找不到文件 u<   请检查文件路径是否正确，以及文件是否存在   处理JSON文件 r   )r   replace_in_json_objectr   r   dumpr&   FileNotFoundErrorr%   )r   r'   r(   r)   datamodifiedr   r,   r	   r	   r
   r"   H   s*   r"   c           	      C      d}t | tr>|  D ]0\}}||kr+||kr+|| |< d}td| d| d|  qt |ttfr;t||||r;d}q|S t | tr\t| D ]\}}t |ttfr[t||||r[d}qG|S )u2   
    递归查找并替换JSON对象中的值
    FT   已替换: :  -> )
isinstancedictitemsr&   listr4   	enumerate	objr'   r(   r)   r8   keyvalueiitemr	   r	   r
   r4   f   &   

r4   c              
   C   s   zKt | d}t|}W d   n1 sw   Y  t||||}|rIt | d}t|| W d   n1 s:w   Y  td|   W dS W dS  tyh } ztd|  d|  W Y d}~dS d}~ww )	u9   
    在plist文件中查找并替换特定键的值
    rbNwb   已更新plist文件: TF   处理plist文件 r   )r   plistlibloadreplace_in_plist_objectr5   r&   r%   )r   r'   r(   r)   r   r7   r8   r,   r	   r	   r
   r#      s&   r#   c           	      C   r9   )u3   
    递归查找并替换plist对象中的值
    FTr:   r;   r<   )r=   r>   r?   r&   r@   rO   rA   rB   r	   r	   r
   rO      rH   rO   c              
   C   s  zmt | ddd}| }W d   n1 sw   Y  dt| dt| d}d| d| d}t|||\}}	|	dkrkt | d	dd}|| W d   n1 sXw   Y  td
|  d|	 d W dS W dS  ty }
 ztd|  d|
  W Y d}
~
dS d}
~
ww )uC   
    在文本文件中查找并替换特定模式的字符串
    r   r   r   N"z	"\s*:\s*"z": "r   r.      已在文件     中替换     处匹配项TF   处理文本文件 r   r   r   r   escapesubnwriter&   r%   )r   r'   r(   r)   r   r   patternreplacementnew_contentcountr,   r	   r	   r
   r$      s&   
r$   c                 C   s*   t j| \}}| }|tjv p|dv S )u+   
    检查文件是否应该被处理
    )r   r   )r   r   r    r!   r   list_support_open_file_type)r   r*   r+   r	   r	   r
   is_valid_file   s   r^   c                 C   s"   |  d o|  d o| tjvS )u+   
    检查目录是否应该被处理
    z
.xcodeprojz
.framework)endswithr   list_folder_ignore_all)dir_namer	   r	   r
   is_valid_dir   s
   
rb   c           	         s   |st j}td|  d| d|  d}tj|ddD ]4\ }}dd |D |d	d	<  fd
d|D |d	d	< |D ]}tj |}t|| ||rN|d7 }q:qtd| d |S )ui  
    在整个项目中查找并替换特定字符串

    参数:
        search_key (str): 要查找的键名，如 'xxpk_startid'
        old_value (str): 要替换的旧值
        new_value (str): 新的值
        project_path (str, optional): 项目路径，默认使用 oc_util.path_mix_project

    返回:
        int: 成功替换的文件数量
    u#   开始在项目中查找并替换: r;   r<   r   Ttopdownc                 S      g | ]}t |r|qS r	   rb   .0dr	   r	   r
   
<listcomp>      z&replace_in_project.<locals>.<listcomp>Nc                    "   g | ]}t tj |r|qS r	   r^   r   r   joinrh   r   rootr	   r
   rj        "       替换完成，共处理 
    个文件)r   path_mix_projectr&   r   walkr   rn   r-   )	r'   r(   r)   project_pathsuccess_countdirsfilesnamer   r	   rp   r
   replace_in_project   s   r}   c              
   C   s   zTt | ddd}| }W d   n1 sw   Y  ||v rR|||}t | ddd}|| W d   n1 s=w   Y  td|  d| d|  W d	S W d
S  tyq } ztd|  d|  W Y d}~d
S d}~ww )u  
    直接替换文件中的指定文本，不需要键名

    参数:
        file_path (str): 文件路径
        old_text (str): 要替换的旧文本
        new_text (str): 新的文本

    返回:
        bool: 操作成功返回 True，否则返回 False
    r   r   r   Nr.   rQ   u    中直接替换文本: r<   TFr   r   )r   r   replacerX   r&   r%   )r   old_textnew_textr   r   r[   r,   r	   r	   r
   replace_text_directly  s"   
r   c                       |st j}td|  d|  d}tj|ddD ]3\ }}dd |D |dd<  fd	d|D |dd< |D ]}tj |}t|| |rJ|d
7 }q7qtd| d |S )u%  
    在整个项目中直接替换指定文本

    参数:
        old_text (str): 要替换的旧文本
        new_text (str): 新的文本
        project_path (str, optional): 项目路径，默认使用 oc_util.path_mix_project

    返回:
        int: 成功替换的文件数量
    u&   开始在项目中直接替换文本: r<   r   Trc   c                 S   re   r	   rf   rg   r	   r	   r
   rj   L  rk   z+replace_text_in_project.<locals>.<listcomp>Nc                    rl   r	   rm   ro   rp   r	   r
   rj   O  rr   rs   rt   ru   )r   rv   r&   r   rw   r   rn   r   )r   r   rx   ry   rz   r{   r|   r   r	   rp   r
   replace_text_in_project5     r   c              
   C   s   z)t j| \}}| }|dkrt| ||W S |dkr#t| ||W S t| ||W S  tyF } ztd|  d|  W Y d}~dS d}~ww )u  
    在指定文件中查找键名并替换其值

    参数:
        file_path (str): 文件路径
        search_key (str): 要查找的键名，如 'xxpk_startid'
        new_value (str): 新的值

    返回:
        bool: 操作成功返回 True，否则返回 False
    r   r   r   r   NF)	r   r   r    r!   replace_key_in_json_filereplace_key_in_plist_filereplace_key_in_text_filer%   r&   )r   r'   r)   r*   r+   r,   r	   r	   r
   replace_key_in_fileZ  s   r   c              
   C   s   z:t | }t|||\}}|r8t| ddd}tj||dd W d   n1 s)w   Y  td|   W dS W d	S  tyW } ztd
|  d|  W Y d}~d	S d}~ww )u5   
    在JSON文件中查找键名并替换其值
    r.   r   r   r/   r0   Nr2   TFr3   r   )r   replace_key_in_json_objectr   r   r5   r&   r%   )r   r'   r)   r7   r8   r*   r   r,   r	   r	   r
   r   y  s   r   c                 C      d}d}t | trE|  D ]3\}}||kr+|}|| |< d}td| d| d|  qt |ttfr@t|||\}}|r@d}|}q||fS t | trht| D ]\}	}
t |
ttfrgt|
||\}}|rgd}|}qN||fS )un   
    递归查找并替换JSON对象中的键值

    返回:
        (bool, str): (是否修改, 旧值)
    FNTr:   r;   r<   )r=   r>   r?   r&   r@   r   rA   rC   r'   r)   r8   r(   rD   rE   sub_modifiedsub_old_valuerF   rG   r	   r	   r
   r     :   

r   c              
   C   s   zLt | d}t|}W d   n1 sw   Y  t|||\}}|rJt | d}t|| W d   n1 s;w   Y  td|   W dS W dS  tyi } ztd|  d|  W Y d}~dS d}~ww )	u6   
    在plist文件中查找键名并替换其值
    rI   NrJ   rK   TFrL   r   )r   rM   rN   replace_key_in_plist_objectr5   r&   r%   )r   r'   r)   r   r7   r8   r*   r,   r	   r	   r
   r     s"   r   c                 C   r   )uo   
    递归查找并替换plist对象中的键值

    返回:
        (bool, str): (是否修改, 旧值)
    FNTr:   r;   r<   )r=   r>   r?   r&   r@   r   rA   r   r	   r	   r
   r     r   r   c           
   
      s  zdt | ddd}| }W d   n1 sw   Y  dt| d} fdd}t|||\}}|d	krbt | d
dd}|| W d   n1 sOw   Y  td|  d| d W dS W dS  ty }	 ztd|  d|	  W Y d}	~	dS d}	~	ww )u7   
    在文本文件中查找键名并替换其值
    r   r   r   Nz("z"\s*:\s*")([^"]*)(")c                    s   |  d   |  d S )Nrs      )group)matchr)   r	   r
   replace_func  s   z.replace_key_in_text_file.<locals>.replace_funcr   r.   rQ   rR   rS   TFrT   r   rU   )
r   r'   r)   r   r   rY   r   r[   r\   r,   r	   r   r
   r     s&   
r   c                    r   )u:  
    在整个项目中查找键名并替换其值

    参数:
        search_key (str): 要查找的键名，如 'xxpk_startid'
        new_value (str): 新的值
        project_path (str, optional): 项目路径，默认使用 oc_util.path_mix_project

    返回:
        int: 成功替换的文件数量
    u   开始在项目中查找键 u    并替换为新值: r   Trc   c                 S   re   r	   rf   rg   r	   r	   r
   rj   0  rk   z*replace_key_in_project.<locals>.<listcomp>Nc                    rl   r	   rm   ro   rp   r	   r
   rj   3  rr   rs   rt   ru   )r   rv   r&   r   rw   r   rn   r   )r'   r)   rx   ry   rz   r{   r|   r   r	   rp   r
   replace_key_in_project  r   r   c                  C   s  ddl } t| jdk rAtd td td td td td	 td
 td td td td td td dS | jd }|dkrtt| jdk rWtd dS | jd }| jd }| jd }| jd }t|||| dS |dkrt| jdk rtd dS | jd }| jd }| jd }t||| dS |dkrt| jdk rtd dS | jd }| jd }| jd }t||| dS |dkrt| jdk rtd dS | jd }| jd }t|| dS |dkrt| jdk rtd dS | jd }| jd }| jd }t||| dS |d kr3t| jdk r"td! dS | jd }| jd }t	|| dS td"|  td# dS )$u"  
    主函数，用于命令行调用

    用法示例:
    1. 替换指定文件中的特定字符串:
       python -m ObjectiveC.oc_custom.custom_replace file /path/to/file.json xxpk_startid 352e8711bcca025e07230a8402f03d09 new_value

    2. 在整个项目中查找并替换:
       python -m ObjectiveC.oc_custom.custom_replace project xxpk_startid 352e8711bcca025e07230a8402f03d09 new_value

    3. 直接替换指定文件中的文本:
       python -m ObjectiveC.oc_custom.custom_replace text_file /path/to/file.txt 352e8711bcca025e07230a8402f03d09 new_value

    4. 在整个项目中直接替换文本:
       python -m ObjectiveC.oc_custom.custom_replace text_project 352e8711bcca025e07230a8402f03d09 new_value

    5. 替换指定文件中的键值(不需要提供旧值):
       python -m ObjectiveC.oc_custom.custom_replace key_file /path/to/file.json xxpk_startid new_value

    6. 在整个项目中查找键并替换其值(不需要提供旧值):
       python -m ObjectiveC.oc_custom.custom_replace key_project xxpk_startid new_value
    r   N   u   用法:u+   1. 替换指定文件中的特定字符串:u_      python -m ObjectiveC.oc_custom.custom_replace file <文件路径> <键名> <旧值> <新值>u%   2. 在整个项目中查找并替换:uS      python -m ObjectiveC.oc_custom.custom_replace project <键名> <旧值> <新值>u(   3. 直接替换指定文件中的文本:ua      python -m ObjectiveC.oc_custom.custom_replace text_file <文件路径> <旧文本> <新文本>u(   4. 在整个项目中直接替换文本:uU      python -m ObjectiveC.oc_custom.custom_replace text_project <旧文本> <新文本>u9   5. 替换指定文件中的键值(不需要提供旧值):uZ      python -m ObjectiveC.oc_custom.custom_replace key_file <文件路径> <键名> <新值>uE   6. 在整个项目中查找键并替换其值(不需要提供旧值):uN      python -m ObjectiveC.oc_custom.custom_replace key_project <键名> <新值>rs   file   uI   替换指定文件需要提供: <文件路径> <键名> <旧值> <新值>r   r/      projectu4   项目替换需要提供: <键名> <旧值> <新值>	text_fileuF   直接替换文本需要提供: <文件路径> <旧文本> <新文本>text_projectu@   项目中直接替换文本需要提供: <旧文本> <新文本>key_fileuL   替换指定文件中的键值需要提供: <文件路径> <键名> <新值>key_projectu@   项目中查找键并替换其值需要提供: <键名> <新值>u   未知模式: uK   可用模式: file, project, text_file, text_project, key_file, key_project)
syslenargvr&   r-   r}   r   r   r   r   )r   moder   r'   r(   r)   r   r   r	   r	   r
   main>  s   



















r   c              
   C   sL   z
t ||| }|W S  ty% } ztd|  | W  Y d}~S d}~ww )u   
    在内容中使用正则表达式替换匹配的模式

    参数:
        content (str): 要处理的内容
        pattern (str): 正则表达式模式
        replacement (str): 替换的内容

    返回:
        str: 替换后的内容
    u    正则表达式替换时出错: Nr   r   r%   r&   )r   rY   rZ   r[   r,   r	   r	   r
   replace_pattern_in_content  s   r   c              
   C   s^   z| }|D ]\}}t |||}q|W S  ty. } ztd|  | W  Y d}~S d}~ww )u   
    在内容中使用多个正则表达式模式进行替换

    参数:
        content (str): 要处理的内容
        pattern_replacements (list): 包含 (pattern, replacement) 元组的列表

    返回:
        str: 替换后的内容
    u)   多模式正则表达式替换时出错: Nr   )r   pattern_replacementsresult_contentrY   rZ   r,   r	   r	   r
   $replace_multiple_patterns_in_content  s   r   c              
   C   s   z&t j| \}}| }|dkrt| |W S |dkr!t| |W S t| |W S  tyC } ztd|  d|  W Y d}~dS d}~ww )u"   
    从文件中获取键值
    r   r   r   r   N)	r   r   r    r!   get_key_value_from_json_fileget_key_value_from_plist_fileget_key_value_from_text_filer%   r&   )r   r'   r*   r+   r,   r	   r	   r
   get_key_value_from_file  s   r   c              
   C   sP   z
t | }t||W S  ty' } ztd|  d|  W Y d}~dS d}~ww )u&   
    从JSON文件中获取键值
    r3   r   N)r   get_key_value_from_json_objectr%   r&   )r   r'   r7   r,   r	   r	   r
   r     s   r   c                 C      t | tr,|  D ] \}}||kr|  S t |ttfr)t||}|dur)|  S q	dS t | trJ| D ]}t |ttfrIt||}|durI|  S q3dS )u,   
    递归查找JSON对象中的键值
    N)r=   r>   r?   r@   r   rC   r'   rD   rE   resultrG   r	   r	   r
   r     $   



r   c              
   C   s|   z t | d}t|}W d   n1 sw   Y  t||W S  ty= } ztd|  d|  W Y d}~dS d}~ww )u'   
    从plist文件中获取键值
    rI   NrL   r   )r   rM   rN   get_key_value_from_plist_objectr%   r&   )r   r'   r   r7   r,   r	   r	   r
   r     s   r   c                 C   r   )u-   
    递归查找plist对象中的键值
    N)r=   r>   r?   r@   r   r   r	   r	   r
   r   '  r   r   c              
   C   s   z5t | ddd}| }W d   n1 sw   Y  dt| d}t||}|r3|dW S W dS  tyR } ztd|  d	|  W Y d}~dS d}~ww )
u(   
    从文本文件中获取键值
    r   r   r   NrP   z"\s*:\s*"(.*?)"rs   rT   r   )r   r   r   rV   searchr   r%   r&   )r   r'   r   r   rY   r   r,   r	   r	   r
   r   <  s   
r   __main__)N)&__doc__r   r   r   rM   
ObjectiveCr   r   r   r   r-   r"   r4   r#   rO   r$   r^   rb   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __name__r	   r	   r	   r
   <module>   sN     
	&
$%&&
!%r
