Skip to main content
Example scripts
arrow icon
To homepage
Bitbucket
Data centre icon
Data Center

Block Unicode Bidirectional Control Characters

Features
Merge checks
Created 1 year ago, Updated 5 month(s) ago
App in script
ScriptRunner For Bitbucket
ScriptRunner For Bitbucket
by Adaptavist
Compatibility
compatibility bullet
Bitbucket (6.0 - 7.17)
compatibility bullet
ScriptRunner For Bitbucket (7.10.0)
Language |
groovy
import com.atlassian.bitbucket.content.AbstractChangeCallback
import com.atlassian.bitbucket.content.AbstractDiffContentCallback
import com.atlassian.bitbucket.content.Change
import com.atlassian.bitbucket.content.ConflictMarker
import com.atlassian.bitbucket.content.DiffSegmentType
import com.atlassian.bitbucket.hook.repository.RepositoryHookResult
import com.atlassian.bitbucket.pull.PullRequestChangesRequest
import com.atlassian.bitbucket.pull.PullRequestDiffRequest
import com.atlassian.bitbucket.pull.PullRequestService
import com.atlassian.sal.api.component.ComponentLocator

import javax.annotation.Nonnull
import javax.annotation.Nullable
import java.util.regex.Pattern

def pullRequest = mergeRequest.pullRequest
final bidiCharsPattern = Pattern.compile(/[\u202a\u202b\u202c\u202d\u202e\u2066\u2067\u2068\u2069]/)

def pullRequestService = ComponentLocator.getComponent(PullRequestService)

Set<String> blockedFiles = []

def changeCallback = new AbstractChangeCallback() {

    @Override
    boolean onChange(@Nonnull Change change) throws IOException {

        pullRequestService.streamDiff(new PullRequestDiffRequest.Builder(pullRequest, change.path.toString()).build(), new AbstractDiffContentCallback() {

            private DiffSegmentType type

            @Override
            void onSegmentStart(@Nonnull DiffSegmentType type) throws IOException {
                this.type = type
                super.onSegmentStart(type)
            }

            @Override
            void onSegmentLine(
                @Nonnull String line, @Nullable ConflictMarker marker, boolean truncated
            ) {
                if (type == DiffSegmentType.ADDED) {
                    if (bidiCharsPattern.matcher(line)) {
                        blockedFiles << change.path.toString()
                    }
                }
            }
        })

        true
    }
}

pullRequestService.streamChanges(new PullRequestChangesRequest.Builder(pullRequest).withComments(false).build(), changeCallback)

if (blockedFiles) {
    RepositoryHookResult.rejected("Merge rejected", "Diff contains illegal Unicode bidirectional characters in ${blockedFiles.join(', ')}")
}
Having an issue with this script?
Report it here