def list_all_files(i):
    """
    Input:  {
              path                  - top level path
              (file_name)           - search for a specific file name
              (pattern)             - return only files with this pattern
              (path_ext)            - path extension (needed for recursion)
              (can_be_dir)          - if 'yes', return matched directories as well
              (recursion_level_max) - if >0, limit dir recursion
            }

    Output: {
              return       - return code =  0, if successful
                                         >  0, if error
              (error)      - error text if return > 0

              list         - list of found files
            }
    """

    import sys
    import os

    list_of_results=[]

    fname               = i.get('file_name', '')
    fname_with_sep_bool = fname.find(os.sep)>=0

    can_be_dir          = i.get('can_be_dir', '')
    can_be_dir_bool     = can_be_dir == 'yes'

    pattern=i.get('pattern','')
    if pattern!='':
        import fnmatch

    pe = i.get('path_ext', '')
    po = i.get('path', '')
    if sys.version_info[0]<3: po=unicode(po)

    rl=i.get('recursion_level',0)
    rlm=i.get('recursion_level_max',0)

    if rl>rlm:
        return {'return':0, 'list':[]}

    try:
        dirList=os.listdir(po)
    except Exception as e:
        pass
    else:
        for fn in dirList:
            p=''
            try:
                p=os.path.join(po, fn)
            except Exception as e:
                pass

            if p!='':
                candidate = None
                if fname!='':
                    if fname_with_sep_bool and os.path.isdir(p):
                        deep_candidate = os.path.join(po, fname)
                        if os.path.exists( deep_candidate ):
                            candidate = deep_candidate

                    elif fname==fn:
                        candidate = p

                elif pattern!='' and fnmatch.fnmatch(fn, pattern):
                    candidate = p

                if candidate and (candidate not in list_of_results):
                    if os.path.isfile( candidate ) or (can_be_dir_bool and os.path.isdir( candidate )):
                        list_of_results.append( candidate )

                if _internal_check_encoded_path_is_dir(p):
                    r=list_all_files({'path':p, 'path_ext':os.path.join(pe, fn),
                                   'pattern':pattern, 'file_name':fname, 'can_be_dir':can_be_dir,
                                   'recursion_level':rl+1, 'recursion_level_max':rlm})
                    if r['return']>0: return r
                    list_of_results.extend( r.get('list',[]) )

    return {'return':0, 'list':list_of_results}