Exemplo n.º 1
0
def postImage(session, attachImageFilename: str, federationList: [],
              inboxUrl: str, headers: {}, capability: str) -> str:
    """Post an image to the inbox of another person or outbox via c2s
    Supplying a capability, such as "inbox:write"
    """
    # always allow capability requests
    if not capability.startswith('cap'):
        # check that we are posting to a permitted domain
        if not urlPermitted(inboxUrl, federationList, capability):
            print('postJson: ' + inboxUrl + ' not permitted')
            return None

    if not (attachImageFilename.endswith('.jpg') or \
            attachImageFilename.endswith('.jpeg') or \
            attachImageFilename.endswith('.png') or \
            attachImageFilename.endswith('.gif')):
        print('Image must be png, jpg, or gif')
        return None
    if not os.path.isfile(attachImageFilename):
        print('Image not found: ' + attachImageFilename)
        return None
    contentType = 'image/jpeg'
    if attachImageFilename.endswith('.png'):
        contentType = 'image/png'
    if attachImageFilename.endswith('.gif'):
        contentType = 'image/gif'
    headers['Content-type'] = contentType

    with open(attachImageFilename, 'rb') as avFile:
        mediaBinary = avFile.read()
        postResult = session.post(url=inboxUrl,
                                  data=mediaBinary,
                                  headers=headers)
        return postResult.text
    return None
Exemplo n.º 2
0
def postJsonString(session,postJsonStr: str, \
                   federationList: [], \
                   inboxUrl: str, \
                   headers: {}, \
                   capability: str, \
                   debug: bool) -> bool:
    """Post a json message string to the inbox of another person
    Supplying a capability, such as "inbox:write"
    NOTE: Here we post a string rather than the original json so that
    conversions between string and json format don't invalidate
    the message body digest of http signatures
    """

    # always allow capability requests
    if not capability.startswith('cap'):
        # check that we are posting to a permitted domain
        if not urlPermitted(inboxUrl, federationList, capability):
            print('postJson: ' + inboxUrl + ' not permitted by capabilities')
            return None

    postResult = session.post(url=inboxUrl, data=postJsonStr, headers=headers)
    if postResult.status_code < 200 or postResult.status_code > 202:
        if postResult.status_code == 401:
            print('WARN: >>> Post to ' + inboxUrl + ' is unauthorized <<<')
        else:
            print('WARN: Failed to post to ' + inboxUrl)
            print('status code ' + str(postResult.status_code))
        return False
    return True
Exemplo n.º 3
0
def undoAnnounce(session,baseDir: str,federationList: [], \
                 nickname: str, domain: str, port: int, \
                 toUrl: str, ccUrl: str, httpPrefix: str, \
                 objectUrl: str, saveToFile: bool, \
                 clientToServer: bool, \
                 sendThreads: [],postLog: [], \
                 personCache: {},cachedWebfingers: {}, \
                 debug: bool) -> {}:
    """Undoes an announce message
    Typically toUrl will be https://www.w3.org/ns/activitystreams#Public
    and ccUrl might be a specific person whose post was repeated and the
    objectUrl is typically the url of the message which was repeated,
    corresponding to url or atomUri in createPostBase
    """
    if not urlPermitted(objectUrl,federationList,"inbox:write"):
        return None

    if ':' in domain:
        domain=domain.split(':')[0]
    fullDomain=domain
    if port:
        if port!=80 and port!=443:
            if ':' not in domain:
                fullDomain=domain+':'+str(port)

    newUndoAnnounce = {
        "@context": "https://www.w3.org/ns/activitystreams",
        'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname,
        'type': 'Undo',
        'cc': [],
        'to': [toUrl],
        'object': {
            'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname,
            'cc': [],
            'object': objectUrl,
            'to': [toUrl],
            'type': 'Announce'
        }
    }
    if ccUrl:
        if len(ccUrl)>0:
            newUndoAnnounce['object']['cc']=[ccUrl]

    announceNickname=None
    announceDomain=None
    announcePort=None
    if '/users/' in objectUrl or '/profile/' in objectUrl:
        announceNickname=getNicknameFromActor(objectUrl)
        announceDomain,announcePort=getDomainFromActor(objectUrl)

    if announceNickname and announceDomain:
        sendSignedJson(newUndoAnnounce,session,baseDir, \
                       nickname,domain,port, \
                       announceNickname,announceDomain,announcePort, \
                       'https://www.w3.org/ns/activitystreams#Public', \
                       httpPrefix,True,clientToServer,federationList, \
                       sendThreads,postLog,cachedWebfingers,personCache,debug)
            
    return newUndoAnnounce
Exemplo n.º 4
0
def postJson(session, postJsonObject: {}, federationList: [], inboxUrl: str,
             headers: {}, capability: str) -> str:
    """Post a json message to the inbox of another person
    Supplying a capability, such as "inbox:write"
    """

    # always allow capability requests
    if not capability.startswith('cap'):
        # check that we are posting to a permitted domain
        if not urlPermitted(inboxUrl, federationList, capability):
            print('postJson: ' + inboxUrl + ' not permitted')
            return None

    postResult = session.post(url=inboxUrl,
                              data=json.dumps(postJsonObject),
                              headers=headers)
    return postResult.text
Exemplo n.º 5
0
def createAcceptReject(baseDir: str,federationList: [], \
                       nickname: str,domain: str,port: int, \
                       toUrl: str,ccUrl: str,httpPrefix: str, \
                       objectJson: {},ocapJson,acceptType: str) -> {}:
    """Accepts or rejects something (eg. a follow request or offer)
    Typically toUrl will be https://www.w3.org/ns/activitystreams#Public
    and ccUrl might be a specific person favorited or repeated and
    the followers url objectUrl is typically the url of the message,
    corresponding to url or atomUri in createPostBase
    """
    if not objectJson.get('actor'):
        return None

    if not urlPermitted(objectJson['actor'], federationList, "inbox:write"):
        return None

    if port:
        if port != 80 and port != 443:
            if ':' not in domain:
                domain = domain + ':' + str(port)

    newAccept = {
        "@context": "https://www.w3.org/ns/activitystreams",
        'type': acceptType,
        'actor': httpPrefix + '://' + domain + '/users/' + nickname,
        'to': [toUrl],
        'cc': [],
        'object': objectJson
    }
    if ccUrl:
        if len(ccUrl) > 0:
            newAccept['cc'] = [ccUrl]
    # attach capabilities for follow accept
    if ocapJson:
        newAccept['capabilities'] = ocapJson
    return newAccept
Exemplo n.º 6
0
def createDelete(session,baseDir: str,federationList: [], \
                 nickname: str, domain: str, port: int, \
                 toUrl: str, ccUrl: str, httpPrefix: str, \
                 objectUrl: str,clientToServer: bool, \
                 sendThreads: [],postLog: [], \
                 personCache: {},cachedWebfingers: {}, \
                 debug: bool) -> {}:
    """Creates a delete message
    Typically toUrl will be https://www.w3.org/ns/activitystreams#Public
    and ccUrl might be a specific person whose post is to be deleted
    objectUrl is typically the url of the message, corresponding to url
    or atomUri in createPostBase
    """
    if not urlPermitted(objectUrl, federationList, "inbox:write"):
        return None

    if ':' in domain:
        domain = domain.split(':')[0]
        fullDomain = domain
    if port:
        if port != 80 and port != 443:
            if ':' not in domain:
                fullDomain = domain + ':' + str(port)

    statusNumber, published = getStatusNumber()
    newDeleteId= \
        httpPrefix+'://'+fullDomain+'/users/'+nickname+'/statuses/'+statusNumber
    newDelete = {
        "@context":
        "https://www.w3.org/ns/activitystreams",
        'actor':
        httpPrefix + '://' + fullDomain + '/users/' + nickname,
        'atomUri':
        httpPrefix + '://' + fullDomain + '/users/' + nickname + '/statuses/' +
        statusNumber,
        'cc': [],
        'id':
        newDeleteId + '/activity',
        'object':
        objectUrl,
        'published':
        published,
        'to': [toUrl],
        'type':
        'Delete'
    }
    if ccUrl:
        if len(ccUrl) > 0:
            newDelete['cc'] = [ccUrl]

    deleteNickname = None
    deleteDomain = None
    deletePort = None
    if '/users/' in objectUrl or '/profile/' in objectUrl:
        deleteNickname = getNicknameFromActor(objectUrl)
        deleteDomain, deletePort = getDomainFromActor(objectUrl)

    if deleteNickname and deleteDomain:
        sendSignedJson(newDelete,session,baseDir, \
                       nickname,domain,port, \
                       deleteNickname,deleteDomain,deletePort, \
                       'https://www.w3.org/ns/activitystreams#Public', \
                       httpPrefix,True,clientToServer,federationList, \
                       sendThreads,postLog,cachedWebfingers,personCache,debug)

    return newDelete
Exemplo n.º 7
0
def createAnnounce(session,baseDir: str,federationList: [], \
                   nickname: str, domain: str, port: int, \
                   toUrl: str, ccUrl: str, httpPrefix: str, \
                   objectUrl: str, saveToFile: bool, \
                   clientToServer: bool, \
                   sendThreads: [],postLog: [], \
                   personCache: {},cachedWebfingers: {}, \
                   debug: bool,projectVersion: str) -> {}:
    """Creates an announce message
    Typically toUrl will be https://www.w3.org/ns/activitystreams#Public
    and ccUrl might be a specific person favorited or repeated and the
    followers url objectUrl is typically the url of the message,
    corresponding to url or atomUri in createPostBase
    """
    if not urlPermitted(objectUrl,federationList,"inbox:write"):
        return None

    if ':' in domain:
        domain=domain.split(':')[0]
    fullDomain=domain
    if port:
        if port!=80 and port!=443:
            if ':' not in domain:
                fullDomain=domain+':'+str(port)

    statusNumber,published = getStatusNumber()
    newAnnounceId= \
        httpPrefix+'://'+fullDomain+'/users/'+nickname+'/statuses/'+statusNumber
    newAnnounce = {
        "@context": "https://www.w3.org/ns/activitystreams",
        'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname,
        'atomUri': httpPrefix+'://'+fullDomain+'/users/'+nickname+'/statuses/'+statusNumber,
        'cc': [],
        'id': newAnnounceId+'/activity',
        'object': objectUrl,
        'published': published,
        'to': [toUrl],
        'type': 'Announce'
    }
    if ccUrl:
        if len(ccUrl)>0:
            newAnnounce['cc']=[ccUrl]
    if saveToFile:
        outboxDir = createOutboxDir(nickname,domain,baseDir)
        filename=outboxDir+'/'+newAnnounceId.replace('/','#')+'.json'
        with open(filename, 'w') as fp:
            commentjson.dump(newAnnounce, fp, indent=4, sort_keys=False)

    announceNickname=None
    announceDomain=None
    announcePort=None
    if '/users/' in objectUrl or '/profile/' in objectUrl:
        announceNickname=getNicknameFromActor(objectUrl)
        announceDomain,announcePort=getDomainFromActor(objectUrl)

    if announceNickname and announceDomain:
        sendSignedJson(newAnnounce,session,baseDir, \
                       nickname,domain,port, \
                       announceNickname,announceDomain,announcePort, \
                       'https://www.w3.org/ns/activitystreams#Public', \
                       httpPrefix,True,clientToServer,federationList, \
                       sendThreads,postLog,cachedWebfingers,personCache, \
                       debug,projectVersion)
            
    return newAnnounce